[状压DP]从一个点走过每一个点(旅行商问题)

A.收集纸片

Description

链接:https://ac.nowcoder.com/acm/contest/5713/A
来源:牛客网

我们把房间按照笛卡尔坐标系进行建模之后,每个点就有了一个坐标。
假设现在房子里有些纸片需要被收集,收集完纸片你还要回归到原来的位置,你需要制定一个策略来使得自己行走的距离最短。
你只能沿着 x 轴或 y 轴方向移动,从位置 (i,j) 移动到相邻位置 (i+1,j),(i-1,j),(i,j+1) 或 (i,j-1) 距离增加 1。

Input

在第一行中给出一个T,1≤T≤10T, 1 \le T \le 10T,1T10, 代表测试数据的组数。
对于每组输入,在第一行中给出房间大小,第二行给出你的初始位置。
接下来给出一个正整数 n,1≤n≤10n,1 \le n \le 10n,1n10 代表纸片的个数。
接下来 n 行,每行一个坐标代表纸片的位置。
保证房间小于 20×2020 \times 2020×20,纸片一定位于房间内。

Output

对于每组输入,在一行中输出答案。
格式参见样例。

Examples

Input1
10 10
1 1
4
2 3
5 5
9 4
6 5

Output

The shortest path has length 24

正确解法:

设dp[i][j]  i是目前走过的点集合(状态),j是最后一个点。

枚举每一个状态。

在枚举最后一个点。

若状态中有这个点,开始压缩

枚举所有点。

更新状态。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 //#include <unordered_map>
13 #define mem( a ,x ) memset( a , x ,sizeof(a) )
14 #define rep( i ,x ,y ) for( int i = x ; i<=y ;i++ )
15 #define lson  l ,mid ,pos<<1
16 #define rson mid+1 ,r ,pos<<1|1
17 using namespace std;
18 typedef long long ll ;
19 typedef pair<int ,int> pii;
20 typedef pair<ll ,int> pli;
21 const int inf = 0x3f3f3f3f;
22 const ll mod=998244353;
23 const int N=1e5+50;
24 int T,k1,k2,n;
25 int rk[15];
26 int dis[1<<12][15];
27 struct node
28 {
29     int xx,yy;
30 }a[15];
31 int check(node a,node b)
32 {
33     return abs(a.xx-b.xx)+abs(a.yy-b.yy);
34 }
35 int main()
36 {
37     scanf("%d",&T);
38     while(T--)
39     {
40         scanf("%d%d",&k1,&k2);
41         scanf("%d%d",&a[0].xx,&a[0].yy);
42         scanf("%d",&n);
43         for(int i=1;i<=n;i++)
44             scanf("%d%d",&a[i].xx,&a[i].yy);
45         for(int i=0;i<=1<<11;i++)
46             for(int j=0;j<=10;j++)
47                 dis[i][j]=inf;
48         for(int i=1;i<=n;i++)
49             dis[1<<(i-1)][i]=check(a[0],a[i]);
50         for(int s=0;s<(1<<n);s++)
51         {
52             for(int j=1;j<=n;j++)
53                 if(s&(1<<(j-1)))
54             {
55                 for(int k=1;k<=n;k++)
56                     if(s&(1<<(k-1)))
57                 {
58                     dis[s][j]=min(dis[s][j],dis[s^(1<<(j-1))][k]+check(a[k],a[j]));
59                 }
60             }
61         }
62         int ans=inf;
63         for(int i=1;i<=n;i++)
64             ans=min(ans,dis[(1<<n)-1][i]+check(a[0],a[i]));
65         printf("The shortest path has length %d\n",ans);
66 
67     }
68 
69     return 0;
70 }
View Code

 

posted @ 2020-05-19 20:59  kaike  阅读(170)  评论(0编辑  收藏  举报