HDU 5067 Harry And Dig Machine

来源:互联网 发布:淘宝开店所需资料 编辑:程序博客网 时间:2024/04/30 06:35

题目描述:

点击打开链接

地图上有k个点必须走,而且最后要走回起点,这题或许可以用BFS写?没试过,我在这里用的是DP的写法,不过无论是BFS或者DP,核心还是状态压缩,我觉得状态压缩的题数据一般会有十分明显的提示,通常是有一些的物品的处理情况非常多,但是这种特殊物品的数量又特别少,通常是不超过20,这种时候一般都采取状态压缩的方式,将状态简化之后这题其实是一个非常清晰的关于最短路径的DP,算出每一点的最短距离之后,在枚举该点回到起点的距离,最后找到和的最小值就可以了。关于状态压缩在我之前讲POJ2923中已经讲的比较清楚,那个题如果理解了,那么理解状态压缩并不困难 。
AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<stack>#include<queue>#include<algorithm>using namespace std;const int MAXM=101;const int INF=999999;struct node{    int x;    int y;};int n,m;int ma[MAXM][MAXM];struct node p[MAXM];int dis[MAXM][MAXM];int dp[3010][MAXM];int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        int cnt=0;        memset(p,0,sizeof(p));        for (int i=0;i<n;i++)        {            for (int j=0;j<m;j++)            {                scanf("%d",&ma[i][j]);                if (i==0&&j==0)                {                    p[cnt].x=i;                    p[cnt].y=j;                    cnt++;                }                else if (ma[i][j]!=0)                {                    p[cnt].x=i;                    p[cnt].y=j;                    cnt++;                }            }        }        memset(dis,INF,sizeof(dis));        dis[0][0]=0;        for (int i=0;i<cnt;i++)        {            for (int j=i+1;j<cnt;j++)            {                dis[i][j]=dis[j][i]=abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y);            }        }        memset(dp,INF,sizeof(dp));        dp[0][0]=0;        for (int i=0;i<(1<<cnt);i++)        {            for (int j=0;j<cnt;j++)            {                if (dp[i][j]!=INF)                {                    for (int k=0;k<cnt;k++)                    {                        if ((i>>k)&1) continue;                        if (dis[j][k]==INF) continue;                        dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+dis[j][k]);                    }                }            }        }        int ans=INF;        for (int i=0;i<cnt;i++)            if (dp[(1<<cnt)-1][i]+dis[i][0]<ans)            ans=dp[(1<<cnt)-1][i]+dis[i][0];        printf("%d\n",ans);    }    return 0;}



原创粉丝点击