uva1336 Fixing the Great Wall
Posted w19567
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva1336 Fixing the Great Wall相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVA-1336
显然最佳的移动方式一定是向左走一段,向右走一段,再向左走一段,再向右走一段......(或者反过来)
无论如何中间的会最先被修理好,所以考虑区间dp
$f_i,j,0/1$表示修理好了$i\rightarrow j$时,所用的最小费用(注意费用提前计算)
预处理处$cl_i,j(i\leq j)$表示从$i$出发修理到$j$的费用
$cr_i,j(i\geq j)$从$i$出发修理到$j$的费用
然后就是转移了(其实还是很好想的),由于决策集合不会变小,所以可以用一个标记记录一下最小值,$O(1)$转移
#include<bits/stdc++.h> using namespace std; const int N=1005; const double inf=1000000000.0,eps=0.000001; int n,v,x,st; struct nodeint c,d,x; sec[N]; double f[N][N][2],cl[N][N],cr[N][N]; double sum[N],min0[N],min1[N],bs; void clear() st=0,bs=0; for(int i=0;i<N;++i) sum[i]=0,cl[i][i]=0; min0[i]=min1[i]=inf; double tme(int a,int b) return (double)abs(sec[a].x-sec[b].x)/(double)v; bool cmp(node a,node b) return a.x<b.x; int main() while (scanf("%d%d%d", &n, &v, &x)==3 && n) if(!n && !v && !x) return 0; clear(); for(int i=1;i<=n;++i) scanf("%d%d%d",&sec[i].x,&sec[i].c,&sec[i].d); sort(sec+1,sec+n+1,cmp); sec[n+1].x=x+1; for(int i=1;i<=n+1;++i) if(sec[i].x>x) st=i-1;break; for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) cl[i][j]=cl[i][j-1]+tme(i,j)*sec[j].d; for(int i=1;i<=n;++i) for(int j=i-1;j>=1;--j) cr[i][j]=cr[i][j+1]+tme(i,j)*sec[j].d; for(int i=1;i<=n;++i) sum[i]=sum[i-1]+sec[i].d,bs+=sec[i].c; if(!st) printf("%.0lf\n",floor(bs+cl[1][n]+1.0*(sec[1].x-x)/(1.0*v)*sum[n]+eps)); continue; if(st==n) printf("%.0lf\n",floor(bs+cr[n][1]+1.0*(x-sec[n].x)/(1.0*v)*sum[n]+eps)); continue; f[st][st][0]=f[st][st][1]=1.0*(x-sec[st].x)/(1.0*v)*sum[n]; f[st+1][st+1][0]=f[st+1][st+1][1]=1.0*(sec[st+1].x-x)/(1.0*v)*sum[n]; min0[st]=min1[st]=f[st][st][0]; min0[st+1]=min1[st+1]=f[st+1][st+1][0]; for(int i=2;i<=n;++i) for(int j=max(1,st-i+1);j<=st+1 && i+j-1<=n;++j) int l=j,r=j+i-1; double pre=sum[n]-sum[r]+sum[l-1]; f[l][r][0]=min0[r]+cr[r][l]+tme(r,l)*pre; f[l][r][1]=min1[l]+cl[l][r]+tme(r,l)*pre; min0[r]=min(min0[r],f[l][r][1]-cr[r][l]); min1[l]=min(min1[l],f[l][r][0]-cl[l][r]); //cout<<l<<" "<<r<<" "<<f[l][r][0]<<" "<<f[l][r][1]<<endl; printf("%.0lf\n",floor(min(f[1][n][0],f[1][n][1])+bs+eps)); return 0;
以上是关于uva1336 Fixing the Great Wall的主要内容,如果未能解决你的问题,请参考以下文章
UVa 1336 Fixing the Great Wall (区间DP)
UVA10256 The Great Divide(凸包相交)
UVA 10256 The Great Divide (判断凸包相交)