2488:Tree Construction
問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2488
区間dp。monge性を使わなくても通ってしまった。
dp[i][j]:=i~j番目までの点で木を作るときの最小コスト
#include<vector> #include<iostream> #include<algorithm> #include<map> #include<set> #include<queue> #include<string> #include<cctype> #include<cassert> #include<cmath> #include<climits> #define INF (1<<29) #define all(c) (c).begin(),(c).end() #define D(x) cout << #x " is " << (x) << endl #define rep(i,n) for(int i = 0; i < n; i++) #define x first #define y second using namespace std; typedef pair<int,int>pii; typedef long long ll; int dp[1001][1001]; int main(void){ int n; cin >> n; vector<pii>v(n); rep(i,n)cin >> v[i].x >> v[i].y; fill(dp[0],dp[1001],INT_MAX); rep(i,1001)dp[i][i]=0; for(int w=0;w<n;w++){ for(int i=0;i+w<n;i++){ for(int s=i;s<i+w;s++){ int cost=abs(v[i].x-v[s+1].x)+abs(v[s].y-v[i+w].y); dp[i][i+w]=min(dp[i][i+w],dp[i][s]+dp[s+1][i+w]+cost); } } } cout << dp[0][n-1] << endl; return 0; }
↓がmonge性を使って高速化したもの。
#include<vector> #include<iostream> #include<algorithm> #include<map> #include<set> #include<queue> #include<string> #include<cctype> #include<cassert> #include<cmath> #include<climits> #define INF (1<<29) #define all(c) (c).begin(),(c).end() #define D(x) cout << #x " is " << (x) << endl #define rep(i,n) for(int i = 0; i < n; i++) #define x first #define y second using namespace std; typedef pair<int,int>pii; typedef long long ll; ll dp[1002][1002],K[1002][1002]; int main(void){ int n; cin >> n; vector<pii>v(n); rep(i,n)cin >> v[i].x >> v[i].y; fill(dp[0],dp[1001],INT_MAX); fill(K[0],K[1001],-1); rep(i,1001)dp[i][i]=0,K[i][i]=i; for(int w=1;w<n;w++){ for(int i=0;i+w<=n;i++){ for(int s=K[i][i+w-1];s<=K[i+1][i+w];s++){ int cost=abs(v[i].x-v[s+1].x)+abs(v[s].y-v[i+w].y); if(dp[i][i+w]>dp[i][s]+dp[s+1][i+w]+cost){ dp[i][i+w]=dp[i][s]+dp[s+1][i+w]+cost; K[i][i+w]=s; } } } } cout << dp[0][n-1] << endl; return 0; }