POJ 2677 / ZOJ 2581 : Tour - DP

来源:互联网 发布:淘宝买家秀福利的店铺 编辑:程序博客网 时间:2024/06/06 00:26

双调欧几里德旅行商问题,

(寒假马拉松 第一场 J题)

dps[i][j]代表走的快的人到达i,走的慢的人到达j时的最小距离。

当连接新的点i+1时,如果给j,则j就超过了i,成为了更快的人,下一状态变成dp[i+1][i]。

如果给i,给j保持不变,下一状态为dp[i+1][j]。

由此得到递推公式:

dps[i+1][i] = min(dps[i+1][i], dps[i][j] + dis(j, i+1));

dps[i+1][j] = min(dps[i+1][j], dps[i][j] + dis(i, i+1));

由于最右节点必然是终点,所以走的快的人必然到达了n-1点,最终的距离就是枚举j,dps[n-1][j] + dis(j, n-1)中最小的。


另外可以参考。

#include<iostream>#include<cstdio>#include<cmath>using namespace std;const int N=100;const double X=1e100;//1e100 1乘以10的100次方double dps[N][N];int x[N],y[N];double dis(int x1,int y1,int x2,int y2){return sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2));}double dis(int i,int j){return dis(x[i],y[i],x[j],y[j]);}double min(double x,double y){return x<y?x:y;}int main(){int n;while(~scanf("%d",&n)){int i,j;for(i=0;i<n;i++){scanf("%d%d",&x[i],&y[i]);//printf("%d %d",x[i],y[i]);for(j=0;j<n;j++)dps[i][j]=X;}//puts("");dps[1][0]=dis(1,0);for(i=0;i<n-1;i++)for(j=0;j<i;j++){dps[i+1][i]=min(dps[i+1][i],dps[i][j]+dis(j,i+1));dps[i+1][j]=min(dps[i+1][j],dps[i][j]+dis(i,i+1));}double ans=X;for(j=0;j<n-1;j++){ans=min(ans,dps[n-1][j] + dis(j,n-1));//printf("%.2lf ",ans);}printf("%.2f\n",ans);}return 0;}


0 0
原创粉丝点击