【状压DP_TSP】HDU 5067 Harry And Dig Machine

 HDU 5067 Harry And Dig Machine

题意:有一个n*m的图,每个方格有[0, 100]数量的石子。从(0, 0)出发,到达所有有石子的方格,每个方格都只能经过一次,最终回到(0, 0),两个结点间的距离为曼哈顿距离,问最短路径。

TSP:Traveling Salesman Problem

一个旅行商要拜访n个城市,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是最短路。

图论中著名的问题之一:已给一个n个点的完全图,每条边都有一个长度,求总长度最短的经过每个顶点正好一次的封闭回路。如果两个点之间不存在路径,则增加一条长度为INF的边构成完全图,不影响计算最优回路。

题目中的有石子的方格数量不超过10,所以直接用状压暴力跑所有的状态即可。

dp[now][sta]:当前在位置now,并且之前走过的状态为sta(二进制对应位为1就是走过,对应位为0就是没走过)

状态转移的条件:下一个要走的结点nex没走过,也就是sta | (1 << nex) == 0; 并且当前所在结点走过,也就是sta | (1 << now) == 1

状态转移方程

dp[nex][sta | (1 << nex)] = min(dp[nex][sta | (1 << nex)], dp[now][sta]+dis[now][nex]);

 【其中dis[now][nex]为两点间的曼哈顿距离,在之前初始化过的】

最后的结果是位置为0,并且所有点都走过也就是dp[0][(1 << cnt) - 1];

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <limits>
#include <set>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e4 + 5;
int n, m;
struct node{
    int x, y;
    node(int a = 0, int b = 0): x(a), y(b){}
}info[15];
int dp[15][1 << 15];
int dis[15][15];
int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        int cnt = 0;
        info[cnt ++ ] = node(0, 0);
        for(int i = 0; i < n; i ++ )
        {
            for(int j = 0; j < n; j ++ )
            {
                int val; scanf("%d", &val);
                if(val == 0 || (i == 0 && j == 0))
                    continue;
                info[cnt ++ ] = node(i, j);
            }
        }
        for(int i = 0; i < cnt; i ++ )//初始化有效点间的曼哈顿距离
            for(int j = 0; j < cnt; j ++ )
                dis[i][j] = abs(info[i].x - info[j].x) + abs(info[i].y - info[j].y);
        memset(dp, INF, sizeof(dp));
        for(int i = 0; i < cnt; i ++ )//当前所在位置为i,状态为1 << i的最短路径:就是从点0到点i的距离
            dp[i][1 << i] = dis[0][i];
        for(int sta = 1; sta < (1 << cnt); sta ++ )//枚举状态:对应位置为1即走过,对应位置为0即未走过
            for(int nex = 0; nex < cnt; nex ++ )//枚举下一个位置(更新的也是0->nex的最短路,所以它放到第二层循环)
                for(int now = 0; now < cnt; now ++ )//枚举当前所在的位置
                    if((sta & (1 << now)) && (!(sta & (1 << nex))))//状态转移条件:当前位置在sta里并且下一个位置不在sta里
                        dp[nex][sta | (1 << nex)] = min(dp[nex][sta | (1 << nex)], dp[now][sta] + dis[now][nex]);
        printf("%d\n", dp[0][(1 << cnt) - 1]);
    }
    return 0;
}

二刷……

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <limits>
#include <set>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e4 + 5;
int n, m;
struct node{
    int x, y;
    node(int a = 0, int b = 0) : x(a), y(b) {}
}info[15];
int dp[15][1 << 15];
int dis[15][15];
int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        int cnt = 0;
        info[cnt ++ ] = node(0, 0);
        for(int i = 0; i < n; i ++ )
        {
            for(int j = 0; j < m; j ++ )
            {
                int val; scanf("%d", &val);
                if(val == 0 || (i == 0 && j == 0))
                    continue;
                info[cnt ++ ] = node(i, j);
            }
        }
        for(int i = 0; i < cnt; i ++ )
            for(int j = 0; j < cnt; j ++ )
                dis[i][j] = abs(info[i].x - info[j].x) + abs(info[i].y - info[j].y);
        memset(dp, INF, sizeof(dp));
        for(int i = 0; i < cnt; i ++ )
            dp[i][1 << i] = dis[0][i];
        for(int S = 1; S < (1 << cnt); S ++ )
            for(int nex = 0; nex < cnt; nex ++ )
                for(int now = 0; now < cnt; now ++ )
                    if(S & (1 << now) && !(S & (1 << nex)))
                        dp[nex][S | (1 << nex)] = min(dp[nex][S | (1 << nex)], dp[now][S] + dis[now][nex]);
        printf("%d\n", dp[0][(1 << cnt) - 1]);
    }
    return 0;
}
发布了180 篇原创文章 · 获赞 54 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/103905158
dig