首页 > 代码库 > POJ 3042 Grazing on the Run (区间DP)
POJ 3042 Grazing on the Run (区间DP)
区间dp,~~~~
dp[i][j][0]表示i到j之间已经走过,并且现在在i点的staleness(可以理解为枯萎指数)最小值,
dp[i][j][1]表示i到j之间已经走过,并且现在在j点的staleness最小值。
于是对于在i点,可能从i+1->i,也可能从j->i,即:
很重要的一点,在我们转移到i时,除了即将到达的i点,还有未到达的(n-(j-i+1))个点,即总共(n-(j-i))个点,它们的枯萎指数均在增加,so~
dp[i][j][0]=min(dp[i+1][j][0]+(n-(j-i))*(pos[i+1]-pos[i]),dp[i+1][j][1]+(n-(j-i))*(pos[j]-pos[i]));
同理对于当前在j点,也可以得到向相应的方程:
dp[i][j][1]=min(dp[i][j-1][1]+(n-(j-i))*(pos[j]-pos[j-1),dp[i][j-1][0]+(n-(j-i))*(pos[j]-pos[i])).
最后需要注意的就是初始话的问题了,找到L在原序列中的位置就好。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
题目链接:http://poj.org/problem?id=3042
#include<cstdio> #include<cstring> #include<algorithm> #define N 1000+10 using namespace std; int p[N]; int f[N][N][2]; int main() { int n,s; while(~scanf("%d%d",&n,&s)) { int ok=1; for(int i=0;i<n;i++) { scanf("%d",&p[i]); if(p[i]==s) ok=0; //可能存在某点与起点重合的情况。 } if(ok) p[n++]=s; sort(p,p+n); int pos=lower_bound(p,p+n,s)-p; //二分查找L的位置。 memset(f,0x3f,sizeof(f)); f[pos][pos][0]=f[pos][pos][1]=0; //起点~ for(int i=pos;i>=0;i--) { for(int j=pos;j<n;j++) { f[i][j][0]=min(f[i][j][0],f[i+1][j][0]+(n-(j-i))*(p[i+1]-p[i])); f[i][j][0]=min(f[i][j][0],f[i+1][j][1]+(n-(j-i))*(p[j]-p[i])); f[i][j][1]=min(f[i][j][1],f[i][j-1][1]+(n-(j-i))*(p[j]-p[j-1])); f[i][j][1]=min(f[i][j][1],f[i][j-1][0]+(n-(j-i))*(p[j]-p[i])); } } printf("%d\n",min(f[0][n-1][0],f[0][n-1][1])); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。