山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

vijosP1014 旅行商简化版

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的人的代码都过不了)

【代码】

 

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 1000+10;
 8 struct Node{
 9     double x,y;
10     bool operator<(const Node& rhs) const{
11        return x<rhs.x || (x==rhs.x && y<rhs.y);
12     }
13 }nodes[maxn];
14 double f[maxn][maxn];
15 bool vis[maxn][maxn];
16 int n;
17 
18 inline double dist(int i,int j){
19     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));
20 }
21 
22 double dp(int i,int j) {
23     double &ans=f[i][j];
24     if(vis[i][j]) return ans;
25     vis[i][j]=1;
26     
27     if(i==n) return ans=dist(j,n);
28     
29     return ans=min(dp(i+1,j)+dist(i,i+1),dp(i+1,i)+dist(j,i+1));
30 }
31 
32 int main(){
33     scanf("%d",&n);
34     for(int i=1;i<=n;i++) scanf("%lf%lf",&nodes[i].x,&nodes[i].y);
35     sort(nodes+1,nodes+n+1);
36     if(n==1) printf("0.00\n");
37     else printf("%.2lf\n",dp(2,1)+dist(1,2));    
38     return 0;
39 }

 PS:相比较而言,记忆化搜索要比递推写法简单,只需要设定好返回边界即可,不会有太多的遗漏。

 

posted on 2015-10-23 18:45  hahalidaxin  阅读(252)  评论(0编辑  收藏  举报