CCPC - k题(dp)
2015-10-27 10:54
471 查看
本题目的意思:
给定n个位置,每个位置有一个二元组,要求确定n个位置的属性(选1或者是2),使得每个二元组的1属性和2属性去最近的位置,总代价最小(代价 属性值*移动距离)
分析:
可以尝试如此规划,定义d[ i ][ j ]为当前修到了i位置,i位置的属性为j,那么下面的一段连续路径要修的属性为(3-j),这一段路径上的属性为(3-j)的不需要移动,剩下的要移动到两边。
这个题目难得地方在于怎样设计状态使得具有很好的规划性质。
附: 交题点击打开链接
给定n个位置,每个位置有一个二元组,要求确定n个位置的属性(选1或者是2),使得每个二元组的1属性和2属性去最近的位置,总代价最小(代价 属性值*移动距离)
分析:
可以尝试如此规划,定义d[ i ][ j ]为当前修到了i位置,i位置的属性为j,那么下面的一段连续路径要修的属性为(3-j),这一段路径上的属性为(3-j)的不需要移动,剩下的要移动到两边。
这个题目难得地方在于怎样设计状态使得具有很好的规划性质。
附: 交题点击打开链接
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define rep1(i,x,y) for(int i=x;i<=y;i++) #define rep(i,n) for(int i=0;i<(int)n;i++) using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int N = 4010; int n; struct node { ll pre ,pp ,suf ,ss ; void init() { pre[0]=pp[0]=suf[n+1]=ss[n+1]=0; rep1(i,1,n) pre[i]=pre[i-1]+pre[i],pp[i]=pre[i]+pp[i-1]; for(int i=n; i>=1; i--) suf[i]=suf[i+1]+suf[i],ss[i]=ss[i+1]+suf[i]; } ll get_lr(int i,int j) { int mid=(j-i-1)/2+i , llen = mid-i , rlen = j-mid-1; ll sum = 0; sum+=ss[i+1]-ss[mid+1]-suf[mid+1]*llen; sum+=pp[j-1]-pp[mid]-pre[mid]*rlen; return sum; } ll get(int i,int j) { if(i == 0) return pp[j-1]; else if(j == n+1) return ss[i+1]; return get_lr(i,j); } } T,P; ll d [2]; bool vis [2]; ll dp(int i,int j) { if(vis[i][j]) return d[i][j]; vis[i][j] = true; if(i == n) return d[i][j] = 0; int lim = (i==0 ? n-1 : n); rep1(k,i+1,lim) { ll add=(j==0 ? T.get(i,k+1):P.get(i,k+1)); if(k == i+1) d[i][j] = dp(k,j^1)+add; else d[i][j] = min(d[i][j],dp(k,j^1)+add); } return d[i][j]; } int main() { int Ta,kase=1; scanf("%d",&Ta); while(Ta--) { scanf("%d",&n); int x,y; rep1(i,1,n) scanf("%d %d",&x,&y),T.pre[i]=T.suf[i]=x,P.pre[i]=P.suf[i]=y; T.init(); P.init(); memset(vis,false,sizeof(vis)); cout<<"Case #"<<kase++<<": "<<min(dp(0,0),dp(0,1))<<endl; } return 0; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C++联合体转换成C#结构的实现方法
- C#实现的算24点游戏算法实例分析
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析