【CodeVS2800】 送外卖 最短路+状压DP

首先求出各点之间的最短路,floyed即可,注意是0~n。

然后考虑状压,f[i][j]表示状态为i时访问j点时的最短路和,1表示访问,0表示未访问,然后第j个点所在的位置就是(1<<j)有0存在,例如状态1010,从右至左,点1.3被访问,所以我们要处理第1各点就是(1<<1)。

f[i][j]=min(f[i][j],f[i-(1<<j)][p]+dis[p][j]);

p表示枚举每个点,i-(1<<j)状态回到访问j之前,很详细了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring> 
 4 using namespace std;
 5 int n,ans;
 6 int dp[(1<<16)][16],dis[16][16];
 7 int main()
 8 {
 9     scanf("%d",&n);
10     ans=0x7fffffff;
11     memset(dp,127,sizeof(dp));
12     for (int i=0;i<=n;i++)
13         for (int j=0;j<=n;j++)
14             scanf("%d",&dis[i][j]);
15     for (int k=0;k<=n;k++)
16         for (int i=0;i<=n;i++)
17             for (int j=0;j<=n;j++)
18                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
19     dp[0][0]=0;
20     for (int i=0;i<(1<<(n+1));i++)
21         for (int now=0;now<=n;now++)
22             for (int last=0;last<=n;last++)
23                 if (i&(1<<now))
24                     dp[i][now]=min(dp[i][now],dp[i-(1<<now)][last]+dis[last][now]);
25     for (int i=0;i<=n;i++)
26         ans=min(ans,dp[(1<<(n+1))-1][i]+dis[i][0]); 
27     printf("%d\n",ans);
28     return 0;
29 }
View Code

题目描述 Description

有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的时间。

输入描述 Input Description

第一行一个正整数n (1<=n<=15)

接下来是一个(n+1)*(n+1)的矩阵,矩阵中的数均为不超过10000的正整数。矩阵的i行j列表示第i-1号城市和j-1号城市之间直接通路的时间。当然城市a到城市b的直接通路时间和城市b到城市a的直接通路时间不一定相同,也就是说道路都是单向的。

输出描述 Output Description

一个正整数表示最少花费的时间

样例输入 Sample Input
3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
样例输出 Sample Output

8

数据范围及提示 Data Size & Hint

1<=n<=15

posted @ 2016-04-03 10:40  DMoon  阅读(240)  评论(0编辑  收藏  举报