POJ 2688 简单的TSP问题,状压DP
来源:互联网 发布:openwrt端口转发 编辑:程序博客网 时间:2024/04/30 09:07
题意:
考虑一个被分为 W × H 网格的房间,机器人是矩形的,大小为 1 × 1。房间内的格子被分为干净的,脏的和障碍物三种。机器人不能踏上障碍物,而机器人只要经过一个脏的格子,它就会被清洁成干净的格子。
机器人每步可以向四个方向(上、下、左、右)之一走一步,进入在这个方向上和它相邻的格子。机器人可以经过一个格子多次。
你的任务是求得机器人清理干净整个房间(即把所有的脏格子清洁成干净格子)至少需要走多少步。输入文件包含多个测试点。
每个测试点的第一行包含两个空格分隔的整数 W 和 H。之后 H 行,每行包含一个长度是 W 字符的字符串,字符串中的每个字符表示房间的一个格子,且为以下字符之一:
.:干净格子;
*:脏格子;
x:障碍物;
o:机器人所在位置;
机器人所在位置是一个干净格子。
输入文件以 0 0 结尾。对于每个测试点,在单独的一行内输出答案。
如果无解,输出 -1。
TSP问题好难的样子,好像要用什么蚁群算法?
不过这种数据范围小的可以直接用状压DP水过。
标准做法就是f[i][S]表示当前在i,未经过的点的集合是S时还需要最少的步数。
对于这道题,因为脏点不超过10个,所以可以用状压DP,复杂度O(2^10*10)(因为起点确定,所以是10不是10^2)。
先预处理出TSP问题中的n^2条边,就是每两个脏点之间的最短路。之后直接DP即可。
#include <cstdio>#include <queue>#include <algorithm>#include <cstring>using namespace std; int n, m, num, d[405][405], pos[15], f[15][1<<11];char map[405];bool vis[405];queue <int> q;int id(int x, int y){ return (x-1)*m + y;}void BFS(int i){ vis[i] = 1; d[i][i] = 0; q.push(i); while(!q.empty()){ int u = q.front(); q.pop(); while(map[u] == 'x' && !q.empty()) {u = q.front(); q.pop();} if(map[u] == 'x') break; if(u+1 <= id(n, m) && !vis[u+1] && u % m){ d[i][u+1] = d[i][u] + 1; vis[u+1] = 1; q.push(u+1); } if(u-1 > 0 && !vis[u-1] && u % m != 1){ d[i][u-1] = d[i][u] + 1; vis[u-1] = 1; q.push(u-1); } if(u+m <= id(n, m) && !vis[u+m]){ d[i][u+m] = d[i][u] + 1; vis[u+m] = 1; q.push(u+m); } if(u-m > 0 && !vis[u-m]){ d[i][u-m] = d[i][u] + 1; vis[u-m] = 1; q.push(u-m); } }}int dp(int i, int j){ if(f[i][j] >= 0) return f[i][j]; f[i][j] = 1 << 30; for(int k = 0; k < num; k++) if((j>>k)&1){ f[i][j] = min(f[i][j], dp(k+1, j-(1<<k)) + d[pos[i]][pos[k+1]]); } return f[i][j];}int main(){ while(scanf("%d %d", &m, &n) && n){ memset( d,-1, sizeof d); memset( f,-1, sizeof f); memset(pos, 0, sizeof pos); memset(map, 0, sizeof map); num = 0; for(int i = 1; i <= n; i++){ scanf("%s", map+id(i, 1)); } for(int i = id(n, m); i; i--){ if(map[i] == 'o') pos[0] = i; if(map[i] == '*') pos[++num] = i; } bool flag = 0; for(int i = 0; i <= num; i++){ memset(vis, 0, sizeof vis); BFS(pos[i]); for(int j = 0; j <= num; j++){ if(d[pos[i]][pos[j]] < 0){ flag = 1; break; } } } if(flag) {puts("-1"); continue;} int beg = 0; for(int i = 0; i <= num; i++){ if(i != num) beg += (1 << i); f[i][0] = 0; for(int j = 0; j < num; j++){ if(i == j+1) continue; f[i][1<<j] = d[pos[i]][pos[j+1]]; } } printf("%d\n", dp(0, beg)); } return 0;}
0 0
- POJ 2688 简单的TSP问题,状压DP
- POJ 3311 Hie with the Pie (Floyd + 状压dp 简单TSP问题)
- POJ 2688 TSP问题
- 【DP】 POJ 3311 Hie with the Pie 状压 TSP问题
- poj 3229 简单 TSP 状态压缩dp
- poj 2288(状态压缩dp + TSP问题)
- HDU_3681 TSP问题,状压DP
- poj3311 TSP问题 状压DP
- TSP问题(状压DP求解)
- poj 2688 状态压缩dp解tsp
- POJ 3311状压dp+floyd--TSP问题(货郎担问题||旅行商问题)
- 旅行商问题 TSP问题 状压dp入门 + floyd poj 3311 hdu 5418
- 装压DP及TSP问题的学习
- [POJ 3311]Hie with the Pie——再谈TSP问题的DP解法
- POJ 3311 Hie with the Pie (TSP问题 状压DP解法)
- POJ 3311 Hie with the Pie(TSP问题 状压DP)
- hdu 3001 Travelling (TSP问题,状压dp)
- hdu 4568 (状压dp TSP问题)
- synchronized(class)、synchronized(this)与synchronized(object)的区别分析
- 基于AppDomain的"插件式"开发
- java HashMap
- 从svn中check out maven项目 所遇到的一系列问题:
- IgnoreCaseSort
- POJ 2688 简单的TSP问题,状压DP
- 4034: [HAOI2015]T2 (树链剖分)
- my.ini配置文件引起的"无法启动mysql服务,发生错误1067"
- .bash_profile和.bashrc的区别(如何设置生效)
- Android进阶之大话设计模式
- struts 2的OGNL表达式
- 升级到OSX10.11后cocopods不正常的问题
- springmvc之json格式配置
- listView 设置setSection无效