AOJ : 0145 - Cards

問題概要

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=0145&lang=jp
日本語の問題文があるので説明は省略です.

アルゴリズム

↓この方のプログラムを参考にときました. 結果的にほとんどマネてます.
http://d.hatena.ne.jp/tnn-jp/20091107/1257579814


動的計画法
dp[範囲の左端インデックス][範囲の右端インデックス] で管理.

3重ループをまわしているのは,
範囲の幅の決定(i) -> 範囲の左端インデックス決定(j) -> 山の重ね合わせ位置(k)

漸化式は,
dp[j][j+i] = min(dp[j][j+i], a[j]*b[k]*a[k+1]*b[j+i] + dp[j][k] + dp[k+1][j+i]);


すみません.
さっさと寝たいがために解説が適当です.(4:00)

プログラム

#include <iostream>
#include <vector>
#include <climits>
using namespace std;

#define REP(i,n,m) for(int i=n;i<m;i++)
#define rep(i,n) REP(i,0,n)
#define EREP(i,n,m) for(int i=n;i<=m;i++)
#define erep(i,n) EREP(i,0,n)

typedef pair<int,int> P;

unsigned int dp[101][101];

int main(void){
  int n; cin>>n;
  vector<P> v(n);
  rep(i,n) cin>>v[i].first>>v[i].second;

  erep(i,n){
    erep(j,n) dp[i][j] = INT_MAX;
    dp[i][i] = 0;
  }

  REP(i,1,n){ //幅の決定
    EREP(j,0,n-i){ //開始位置の決定
      REP(k,j,j+i){ //切断位置の決定
        int cost = v[j].first * v[k].second * v[k+1].first * v[j+i].second;
        dp[j][j+i] = min(dp[j][j+i],cost+dp[j][k]+dp[k+1][j+i]);
      }
    }
  }

  cout<<dp[0][n-1]<<endl;

  return 0;
}