牛客小白月赛22 收集纸片(最短汉密尔顿回路)

链接: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);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41645482/article/details/104491740