/**//* 一排按钮,要求从第一个,按到最后一个,再从最后一个按回来 中间可以跳着按,但要求每个按钮有且按一次,求使得相邻按的按钮的分数差之和最小 给出n<=1000个数 参考 http://hi.baidu.com/xiszishu/blog/item/650f5b8e094b07fef11f3667.html
双进程dp 双调tsp 由于最后不会按回1,所以加多一个0按钮,到各个按钮的差异为0 dp[i,j] i < j 表示从一个从0按到i,一个从0按到j的最小代价 转移是枚举i,j哪个下一步按max(i,j)+1 (扩展一步去转移丫,我就不会这个转移了!!!) 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
搜索
最新评论
|
|