[状压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,1≤T≤10, 代表测试数据的组数。
对于每组输入,在第一行中给出房间大小,第二行给出你的初始位置。
接下来给出一个正整数 n,1≤n≤10n,1 \le n \le 10n,1≤n≤10 代表纸片的个数。
接下来 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 }
No matter how you feel, get up , dress up , show up ,and never give up.