题意:给定一个网格图,图中有一些点要求全部走到,问最少的花费是多少,从任意边界进入,任意边界出去,如果不能够全部走到,输出0。

解法:一次spfa从边界上的所有点出发,计算到K个宝藏的最短路,然后计算出任意两个宝藏之间的最短路,最后状态压缩枚举即可。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;// 记得要带走全部的物品 const int INF = 0x3f3f3f3f;
int N, M, K;
int mp[205][205];
int idis[15][15]; // 这个15*15的矩阵用来保留宝藏之间的最短路程
int odis[15];      // 从边界到K个位置的最短距离struct Node {int x, y;
}p[15];int que[1000005];
int dis[40005];
char vis[40005];
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};bool legal(int x, int y) {if (x < 0 || x >= N || y < 0 || y >= M) return false;return true;
}void spfa(int sta, int num) {int front = 0, tail = 0;memset(dis, 0x3f, sizeof (dis));memset(vis, 0, sizeof (vis));que[tail++] = sta;dis[sta] = 0, vis[sta] = 1;while (front < tail) {int cur = que[front++], nxt;vis[cur] = 0;int x = cur / M, y = cur % M;int xx, yy;for (int k = 0; k < 4; ++k) {xx = x + dir[k][0], yy = y + dir[k][1];nxt = xx * M + yy;if (legal(xx, yy)) {if (dis[nxt] > dis[cur] + mp[xx][yy]) {dis[nxt] = dis[cur] + mp[xx][yy];if (!vis[nxt]) {vis[nxt] = 1;que[tail++] = nxt;}}}}}for (int i = 0; i < K; ++i) {idis[num][i] = dis[p[i].x * M + p[i].y];}
}void bspfa() {int front = 0, tail = 0;memset(dis, 0x3f, sizeof (dis));memset(vis, 0, sizeof (vis));for (int i = 0; i < N; ++i) {int k1 = i * M, k2 = i * M + M-1;que[tail++] = k1, que[tail++] = k2;dis[k1] = mp[i][0], dis[k2] = mp[i][M-1]; // 边界点均被初始距离为0加入进来 vis[k1] = vis[k2] = 1;}for (int j = 1; j < M - 1; ++j) {int k1 = j, k2 = (N-1) * M + j;que[tail++] = k1, que[tail++] = k2;dis[k1] = mp[0][j], dis[k2] = mp[N-1][j];vis[k1] = vis[k2] = 1;}while (front < tail) {int cur = que[front++], nxt;vis[cur] = 0;int x = cur / M, y = cur % M;int xx, yy;for (int k = 0; k < 4; ++k) {xx = x + dir[k][0], yy = y + dir[k][1];nxt = xx * M + yy;if (legal(xx, yy)) {if (dis[nxt] > dis[cur] + mp[xx][yy]) {dis[nxt] = dis[cur] + mp[xx][yy];if (!vis[nxt]) {vis[nxt] = 1;que[tail++] = nxt;}}}}}for (int i = 0; i < K; ++i) {odis[i] = dis[p[i].x*M + p[i].y];}
}int f[13][1<<13];
// f[i][j]表示状态为j,并且最后走的位置为i的最少开销 int dfs(int sta, int nxt) {if (~f[nxt][sta] && nxt != -1) {return f[nxt][sta];}if (sta == 0) {return f[nxt][sta] = odis[nxt]; // 从nxt开始进入
    }int ret = INF;for (int i = 0; i < K; ++i) {if (sta&(1 << i)) {if (nxt != -1)ret = min(ret, dfs(sta^(1 << i), i) + idis[i][nxt]);elseret = min(ret, dfs(sta^(1 << i), i) + odis[i] - mp[p[i].x][p[i].y]);// 走i点走出去的
        }}return f[nxt][sta] = ret;
}int solve() {memset(f, 0x3f, sizeof (f));int mask = 1 << K;for (int i = 0; i < K; ++i) f[i][1<<i] = odis[i];for (int i = 2; i < mask; ++i) {if (!(i - (i&(-i)))) continue; // 如果只有一位为1for (int j = 0; j < K; ++j) {if (!(i&(1<<j))) continue;for (int k = 0; k < K; ++k) {f[j][i] = min(f[j][i], f[k][i^(1<<j)] + idis[k][j]);}}}int ret = INF;for (int i = 0; i < K; ++i) {ret = min(ret, f[i][mask-1] + odis[i] - mp[p[i].x][p[i].y]);}return ret;
}int main() {int T;
//    freopen("1.in", "r", stdin);scanf("%d", &T);while (T--) {scanf("%d %d", &N, &M);memset(idis, 0x3f, sizeof (idis));memset(odis, 0x3f, sizeof (odis));for (int i = 0; i < N; ++i) {for (int j = 0; j < M; ++j) {scanf("%d", &mp[i][j]);if (mp[i][j] == -1) mp[i][j] = INF;}}scanf("%d", &K);for (int i = 0; i < K; ++i) {scanf("%d %d", &p[i].x, &p[i].y);}for (int i = 0; i < K; ++i) {spfa(p[i].x * M + p[i].y, i);}bspfa();memset(f, 0xff, sizeof (f));int ret = dfs((1<<K)-1, -1);//    int ret = solve();   // 也可 if (ret == INF) puts("0");else printf("%d\n", ret); }return 0;
}

转载于:https://www.cnblogs.com/Lyush/archive/2013/06/07/3123953.html

HDU-4568 Hunter 状态压缩相关推荐

  1. hdu 4568 Hunter bfs建图+TSP状压DP

    想AC的人请跳过这一段... 题目应该都能读懂.但是个人觉得这题出的很烂,意思太模糊了. 首先,进出次数只能是一次!!这个居然在题目中没有明确说明,让我在当时看到题目的时候无从下手. 因为我想到了这几 ...

  2. hdu 3006(状态压缩)

    题意:给一些集合,取一部分集合合并能够得到多少个新集合. 解题思路:这道题数字最多只有14,可以用状态压缩去做,每一位代表某个数,0代表不取,1代表取这个数.剩下的就是去模拟状态了.不多讲,输入状态压 ...

  3. hdu 5418(状态压缩dp+Floyd)

    点击打开链接 解题思路:这道题目和TSP问题很相似,唯一不同的是同一个点可以重复走几次.... 这道题目只有16个顶点,所以很容易想到状态压缩dp,dp[i][j]表示到达顶点i时的状态为j的最小花费 ...

  4. hdu -4284 Travel(状态压缩)

    题意:小P去旅游,给你n个城市,m条路以及m条路的花费,还有一些特定的城市,这些城市必须经过,并且到达这一城市还要先拿到证,在工作去挣钱: 问你是否能通过所有的特定城市. 题解:状态方程:dp[i|( ...

  5. HDU 3091(动态规划-状态压缩)

    问题描述: One day , Partychen gets several beads , he wants to make these beads a necklace . But not eve ...

  6. hdu 5045 Contest(状态压缩DP)

    题解:我们使用一个二位数组dp[i][j]记录进行到第i个任务时,人组合为j时的最大和(这里的j我们用二进制的每位相应一个人). 详细见代码: #include <iostream> #i ...

  7. hdu 5067(状态压缩dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5067 解题思路:这道题开始想复杂了,想用bfs去求出最短距离,其实没必要,因为题目中没有阻碍关系,所以 ...

  8. HDU 1074 Doing Homework【状态压缩DP】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题意: 给定作业截止时间和完成作业所需时间,比截止时间晚一天扣一分,问如何安排作业的顺序使得最 ...

  9. 点分治问题 ----------- HDU 5977 or 2016年大连ICPC [点分治+状态压缩]

    题目链接 题目大意: 就是给你一颗树,树上有各种权值,权值只有K种k∈[1,10]K种k\in[1,10]K种k∈[1,10],问你有多少路径覆盖了这KKK种权值,n∈[1,5e4]n\in[1,5e ...

最新文章

  1. 商品搜索引擎---推荐系统设计
  2. Android LK Bootlaoder启动概览
  3. 怎么样批量修改html里的内容,批量修改替换多个Word文档中同一内容的方法
  4. [RMAN]数据文件的恢复
  5. 类别不均衡的分类问题
  6. git 推送出现 fatal: The remote end hung up unexpectedly 解决方案
  7. XMLHTTP Get HTML页面时的中文乱码之完全客户端Script解决方案
  8. Netty游戏服务器二
  9. CSS进阶(15)—— CSS世界的层叠规则(上)
  10. 一款用VBS编写的修仙风格打怪游戏
  11. 俄罗斯航空发动机AL-31F(solidworks模型)
  12. 用户细分概念辨析——用户分群与用户分层
  13. 心得-计算机软考之嵌入式系统工程师
  14. Lake Shore低温温度传感器之Cernox
  15. TP-link二级路由器配置
  16. 用MindMaster绘制思维导图
  17. Mac全自动安装brew一键配置国内镜像源
  18. tensorflow之tf.tensordot详解
  19. 办公系统服务器搭建,搭建云桌面办公服务器
  20. 如何在论文中画出漂亮的插图

热门文章

  1. 和我一起作Tess的windbg lab - Lab3, Memory
  2. 关于Plos one 和 SR
  3. 【Python-ML】SKlearn库学习曲线和验证曲线
  4. Oracle\Sqlserver\Mysql\Sybase\DB2五类数据库通信协议
  5. Java键盘交互设计输入法,输入法中暖心的交互细节
  6. hive中如何读取数组_hive解析json嵌套数组
  7. labview叠加白噪声_强化学习中Ornstein-Uhlenbeck噪声是鸡肋吗?
  8. 151. 翻转字符串里的单词
  9. JavaScript 技术篇-js只获取本节点text文本,不包含子节点
  10. C语言 volatile的作用与使用场景