HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)

题目地址:

pid=5067">HDU 5067

经典的TSP旅行商问题模型。

状压DP。

先分别预处理出来每两个石子堆的距离。然后将题目转化成10个城市每一个城市至少经过一次的最短时间模型。然后简单的状压DP就可以。

代码例如以下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL __int64
const int INF=0x3f3f3f3f;
int d[20][20], dp[1<<12][12];
struct node
{
    int x, y;
} stone[20];
int main()
{
    int n, m, i, j, x, cnt, y, tmp, k;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        cnt=0;
        stone[0].x=stone[0].y=0;
        for(i=0; i<n; i++)
        {
            for(j=0; j<m; j++)
            {
                scanf("%d",&x);
                if(x)
                {
                    stone[++cnt].x=i;
                    stone[cnt].y=j;
                }
            }
        }
        for(i=0; i<=cnt; i++)
        {
            for(j=0; j<=i; j++)
            {
                x=abs(stone[i].x-stone[j].x)+abs(stone[i].y-stone[j].y);
                d[i][j]=d[j][i]=x;
            }
        }
        /*for(i=0;i<=cnt;i++)
        {
            for(j=0;j<=cnt;j++)
            {
                printf("%d ",d[i][j]);
            }
            puts("");
        }*/
        memset(dp,INF,sizeof(dp));
        y=1<<cnt;
        dp[y-1][0]=0;
        //printf("%d\n",y);
        for(i=y-1; i>=0; i--)
        {
            for(j=0; j<cnt; j++)
            {
                if(i&(1<<j))
                {
                    tmp=i-(1<<j);
                    if(i==y-1)
                    {
                        dp[tmp][j+1]=dp[i][0]+d[0][j+1];
                        continue ;
                    }
                    for(k=1;k<=cnt;k++)
                    {
                        if(dp[i][k]!=INF)
                        {
                            dp[tmp][j+1]=min(dp[tmp][j+1],dp[i][k]+d[k][j+1]);
                        }
                    }
                }
            }
        }
        int min1=INF;
        for(i=1;i<=cnt;i++)
        {
            dp[0][i]+=d[0][i];
            min1=min(min1,dp[0][i]);
        }
        printf("%d\n",min1==INF?

0:min1);
    }
    return 0;
}
时间: 2024-10-13 21:48:25

HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)的相关文章

HDU 5067 Harry And Dig Machine(状压dp)

感觉这两天怎么老是遇到状压啊.... 数字20以下,首想状压啊... 不过这题犯抽忘记考虑没有石头的时候了啊. 简单的状压:表示状态为j时以第i的作为结束. PS:这题也在表扬大蓝翔的挖掘机技术啊.醉了啊... Harry And Dig Machine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 468    Accepted S

HDOJ 5067 Harry And Dig Machine 状压DP

状压DP....dp[i][j]已经走过的点的状态,目前再j点的最小距离 Harry And Dig Machine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 560    Accepted Submission(s): 210 Problem Description As we all know, Harry Porter le

hdu 5067 Harry And Dig Machine (状态压缩dp)

题目链接 bc上的一道题,刚开始想用这个方法做的,因为刚刚做了一个类似的题,但是想到这只是bc的第二题, 以为用bfs水一下就过去了,结果MLE了,因为bfs的队列里的状态太多了,耗内存太厉害. 题意: 从某一点出发,遍历网格上的一些点,每个点至少访问一次需要的最小时间是多少. 官方题解: 由于Harry的dig machine是无限大的,而装载石头和卸载石头是不费时间的,所以问题可以转化成:从某一点出发,遍历网格上的一些点,每个点至少访问一次需要的最小时间是多少.这就是经典的旅行商问题,考虑到

HDU 5067 Harry And Dig Machine(状压dp)

HDU 5067 Harry And Dig Machine 思路:由于点才10个,在加上一个起点,处理出每个点之间的曼哈顿距离,然后用状压dp搞,状态表示为: dp[i][s],表示在i位置,走过的点集合为s的最小代价 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int N = 15;

HDU 4856 Tunnels (最短路+状压DP)

题意:给你N*N的网格,'.'表示可以走,'#'表示不能走,m条管道,每条管道有起点和终点坐标, Bob每次可以走到相邻的网格花费1s,问Bob走完m条管道要花多少时间:Bob在管道内不计算时间 即计算Bob从管道 i 的出口走到管道 j 的入口的时间Dis(e[i],s[j])的最小和,起点可以任意: 思路:看了题解说是状态压缩DP然后深入理解了下. 首先算出d[e[i]][s[j]]的最短距离,不能到达为-1: dp[i][j] : 表示以 j 为起点状态为 i 的最小值.其中 i 是用十进

hdu 5067 Harry And Dig Machine(BestCoder Round #14)

Harry And Dig Machine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 332    Accepted Submission(s): 104 Problem Description As we all know, Harry Porter learns magic at Hogwarts School. Howeve

HDU 1074:Doing Homework(状压DP)

http://acm.hdu.edu.cn/showproblem.php?pid=1074 Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7704    Accepted Submission(s): 3484 Problem Description Ignatius has just come bac

HDU 6149 Valley Numer II(状压DP)

题目链接 HDU6149 百度之星复赛的题目……比赛的时候并没有做出来. 由于低点只有15个,所以我们可以考虑状压DP. 利用01背包的思想,依次考虑每个低点,然后枚举每个状态. 在每个状态里面任意枚举不在这个状态中的两个点,如果能构成一个valley,那么更新答案. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i,

hdu 2167 方格取数 【状压dp】(经典)

<题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数字周围8个点都不能取,问:取得数字的最大和为多少? 解题分析: 由于对每一个数,有选和不选两种可能,分别对应状态压缩中的1和0,且 n<=15,1<<15不是非常大,因此就可以非常自然的想到状态压缩. 此题要与普通的状压dp不同的是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,