hdu4675 TSP(区间DP + 记录转移)

长春Online的题目,

当时读了就推出了分治+记忆化搜索,其实就是区间DP。时间不够就没写,还是太弱了。这种题目,代码量,应该在30min内A掉。

 

dp[i][j][k]表示处理(i,j)内,先访问k+的最小路程。

注意到k==j时,枚举dp[i][j-1][x],路径为:j+ x+ dp[i][j-1][x-1] (j-1)- j-。

k <j时,枚举dp[k+1][j][x],路径为:dp[i][k][k] (k- x+) dp[k+1][j][x]。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 const int maxn = 111;
  9 const double inf = 1000000000;
 10 struct Point
 11 {
 12     double x,y;
 13 } p[maxn][2];
 14 int n;
 15 
 16 double diss(Point a, Point b)
 17 {
 18     return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
 19 }
 20 double dis[maxn][maxn][2][2];
 21 double dp[maxn][maxn][maxn];
 22 int path[maxn][maxn][maxn];
 23 
 24 void dfs_out(int l,int r,int p)
 25 {
 26     if (l == r)
 27     {
 28         printf("%d+ ",p);
 29 
 30         printf("%d-",p);
 31         if (p!=n)
 32         {
 33             printf(" ");
 34         }
 35         return ;
 36     }
 37     int x = path[l][r][p];
 38     if (l < r)
 39     {
 40         if (r == p)
 41         {
 42             printf("%d+ ",p);
 43             dfs_out(l,r-1,x);
 44             printf("%d-",p);
 45             if (p!=n){
 46                 printf(" ");
 47             }
 48         }
 49         else
 50         {
 51             dfs_out(l,p,p);
 52             dfs_out(p+1,r,x);
 53         }
 54     }
 55     return ;
 56 }
 57 int main()
 58 {
 59     while (scanf("%d", &n)==1)
 60     {
 61         for (int i=1; i<=n; i++)
 62         {
 63             for (int j=0; j<2; j++)
 64             {
 65                 scanf("%lf%lf", &p[i][j].x, &p[i][j].y);
 66             }
 67         }
 68         for (int i=1; i<=n; i++)
 69             for (int j=1; j<=n; j++)
 70             {
 71                 for (int ii=0; ii<2; ii++)
 72                     for (int jj=0; jj<2; jj++)
 73                     {
 74                         dis[i][j][ii][jj] = diss(p[i][ii],p[j][jj]);
 75                     }
 76             }
 77 
 78         for (int i=n; i>=1; i--)
 79         {
 80             for (int j=i; j<=n; j++)
 81             {
 82                 if (i == j)
 83                 {
 84                     dp[i][i][i] = dis[i][i][0][1];
 85                     path[i][i][i] = i;
 86                     continue;
 87                 }
 88                 for (int k=i; k<=j; k++)
 89                 {
 90                     if (k==j)
 91                     {
 92                         double tmp = inf;
 93                         for (int x = i; x<j; x++)
 94                         {
 95                             double temp = dp[i][j-1][x] + dis[j][x][0][0] + dis[j-1][j][1][1];
 96                             if (temp < tmp)
 97                             {
 98                                 tmp = temp;
 99                                 path[i][j][k] = x;
100                             }
101                         }
102                         dp[i][j][k] = tmp;
103                     }
104                     else
105                     {
106                         double tmp = inf;
107                         for (int x=k+1; x<=j; x++)
108                         {
109                             double temp = dp[i][k][k] + dp[k+1][j][x] + dis[k][x][1][0];
110                             if (temp < tmp)
111                             {
112                                 tmp = temp;
113                                 path[i][j][k] = x;
114                             }
115                         }
116                         dp[i][j][k] = tmp;
117                     }
118                 }
119             }
120         }
121 
122         double ans = inf;
123         int p = 0;
124         for (int i=1; i<=n; i++)
125         {
126             if (dp[1][n][i] <ans)
127             {
128                 ans = dp[1][n][i];
129                 p = i;
130             }
131         }
132        // printf("%lf\n",ans);
133         dfs_out(1,n,p);
134         puts("");
135     }
136     return 0;
137 }
hdu3675

 

转载于:https://www.cnblogs.com/wangsouc/articles/3363112.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值