 /**//*
一排按鈕,要求從第一個,按到最后一個,再從最后一個按回來
中間可以跳著按,但要求每個按鈕有且按一次,求使得相鄰按的按鈕的分數(shù)差之和最小
給出n<=1000個數(shù)
參考
http://hi.baidu.com/xiszishu/blog/item/650f5b8e094b07fef11f3667.html

雙進程dp 雙調(diào)tsp
由于最后不會按回1,所以加多一個0按鈕,到各個按鈕的差異為0
dp[i,j] i < j
表示從一個從0按到i,一個從0按到j(luò)的最小代價
轉(zhuǎn)移是枚舉i,j哪個下一步按max(i,j)+1 (擴展一步去轉(zhuǎn)移丫,我就不會這個轉(zhuǎn)移了!!!)
dp[i,k] = max(dp[i,k] + dp[i,j] + abs(a[j]-a[k]))
dp[k,j] = max(dp[k,j] + dp[i,j] + abs(a[i]-a[k]))
答案就是dp[n-1,n] + abs(a[n-1]-a[n])

*/
#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<set>
#include<list>
#include<numeric>
#include<cassert>
#include<ctime>

using namespace std;

const int MAXN = 1010;
const int INF = 1000000000;

int a[MAXN];
int dp[MAXN][MAXN];

int main()
  {
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
#endif

 for(int n; ~scanf("%d", &n); ) {
 for(int i = 1 ; i <= n ; i++) {
scanf("%d", &a[i]);
}
fill(dp[0], dp[MAXN], INF);
dp[0][0] = 0;
 for(int i = 0; i < n; i++) {
 for(int j = i; j < n ; j++) {//j = i 因為從[0,0]開始
 if(dp[i][j] >= INF) {
continue;
}
int k = j + 1;
dp[i][k] = min(dp[i][k], dp[i][j] + (j == 0 ? 0 : abs(a[j] - a[k])) );
dp[j][k] = min(dp[j][k] , dp[i][j] + (i == 0 ? 0 : abs(a[i] - a[k])));
}
}
printf("%d\n", dp[n-1][n] + abs(a[n]-a[n-1]));
}
return 0;
}
|
|
常用鏈接
隨筆分類
Links
搜索
最新評論

|
|