您的位置:首页 > 其它

vijosP1014 旅行商简化版

2015-10-23 18:45 218 查看
vijosP1014 旅行商简化版

链接:https://vijos.org/p/1014

【思路】

双线DP。

设ab,ab同时走。用d[i][j]表示ab所处结点i、j,且定义i>j,则有转移方程:

d[i][j]=min{ d[i+1][j]+dist(i,i+1),d[i+1][i]+dist(j,i+1) };

另外需要注意坐标也需要用double读入。

(vj貌似出了些许问题,无论是我的代码还是以前AC的人的代码都过不了)

【代码】

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;

const int maxn = 1000+10;
struct Node{
double x,y;
bool operator<(const Node& rhs) const{
return x<rhs.x || (x==rhs.x && y<rhs.y);
}
}nodes[maxn];
double f[maxn][maxn];
bool vis[maxn][maxn];
int n;

inline double dist(int i,int j){
return sqrt((nodes[i].x-nodes[j].x)*(nodes[i].x-nodes[j].x)+(nodes[i].y-nodes[j].y)*(nodes[i].y-nodes[j].y));
}

double dp(int i,int j) {
double &ans=f[i][j];
if(vis[i][j]) return ans;
vis[i][j]=1;

if(i==n) return ans=dist(j,n);

return ans=min(dp(i+1,j)+dist(i,i+1),dp(i+1,i)+dist(j,i+1));
}

int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&nodes[i].x,&nodes[i].y);
sort(nodes+1,nodes+n+1);
if(n==1) printf("0.00\n");
else printf("%.2lf\n",dp(2,1)+dist(1,2));
return 0;
}


PS:相比较而言,记忆化搜索要比递推写法简单,只需要设定好返回边界即可,不会有太多的遗漏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: