链接:https://ac.nowcoder.com/acm/contest/4462/D
题目描述
我们把房间按照笛卡尔坐标系进行建模之后,每个点就有了一个坐标。
假设现在房子里有些纸片需要被收集,收集完纸片你还要回归到原来的位置,你需要制定一个策略来使得自己行走的距离最短。
你只能沿着 x 轴或 y 轴方向移动,从位置 (i,j) 移动到相邻位置 (i+1,j),(i-1,j),(i,j+1) 或 (i,j-1) 距离增加 1。
题目思路:
很明显普通的dfs,bfs都行不通,但是地图上只有10个纸片,很可能是状态压缩,考虑到地图大小,可以看出这是一个求最小汉密尔顿回路的模板题。只要把纸片的位置抠出来,建图,跑最小汉密尔顿回路模板。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 50;
const int INF = 0x3f3f3f3f;
int g[MAXN][MAXN];
int dp[(1<<16)+10][MAXN];
int xx[15],yy[15],s_x,s_y,k,n,m;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
scanf("%d%d",&s_x,&s_y);
memset(g,0x3f,sizeof(g));
scanf("%d",&k);
n=k+1;
int ss = 1;
for(int i=2;i<=k+1;i++){
scanf("%d%d",&xx[i],&yy[i]);
if(xx[i] ==s_x && yy[i]== s_y)
ss += (1<<(i-1));
}
xx[1] = s_x;
yy[1] = s_y;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j] = g[j][i] = (abs(xx[i]-xx[j]) + abs(yy[i]-yy[j]));
}
}
memset(dp,0x3f,sizeof dp);
dp[1][1]=0;
for(int s=1;s< (1<<n) ; ++s ){
for(int i=1;i<=n;++i){
if(s&(1<<(i-1))){//s中包含i
for(int j=1;j<=n;++j){
if( (s&(1<<(j-1)))==0 ){//s中不包含j
int tt= (s | (1<<(j-1)) );//tt为s包含j的状态
dp[tt][j]=min(dp[tt][j],dp[s][i]+g[i][j]);
}
}
}
}
}
//printf("%d\n",g[n][1] );
int ans=0x3f3f3f3f;
for(int i=2;i<=n;i++)
ans=min(ans,dp[ (1<<n) -1 ][i]+g[i][1]);
printf("The shortest path has length %d\n",ans);
}
}