一道用到二进制位加记忆化搜索的dp题
来源:互联网 发布:linux 获取系统时区 编辑:程序博客网 时间:2024/04/23 22:26
We are planning an orienteering game.
The aim of this game is to arrive at thegoal (G) from the start (S) with the shortest distance.
However, the players have to pass all thecheckpoints (@) on the map.
An orienteering map is to be given in thefollowing format.
########
#@....G#
##.##@##
#..@..S#
#@.....#
########
In this problem, an orienteering map is tobe given.
Calculate the minimum distance from thestart to the goal with passing all the checkpoints.
Specification
* A map consists of 5 characters asfollowing.
You can assume that the map does notcontain any invalid characters and
the map has exactly one start symbol 'S'and exactly one goal symbol 'G'.
* 'S' means the orienteering start.
* 'G' means the orienteering goal.
* '@' means an orienteering checkpoint.
* '.' means an opened-block that playerscan pass.
* '#' means a closed-block that playerscannot pass.
* It is allowed to move only by one stepvertically or horizontally (up, down, left, or right) to the
next block.
Other types of movements, such as movingdiagonally (left up, right up, left down and right down)
and skipping one or more blocks, are NOTpermitted.
* You MUST NOT get out of the map.
* Distance is to be defined as the numberof movements to the different blocks.
* You CAN pass opened-blocks, checkpoints,the start, and the goal more than once if necessary.
* You can assume that parameters satisfyfollowing conditions.
* 1 <= width <= 100
* 1 <= height <= 100
* The maximum number of checkpoints is 18.
* Return -1 if given arguments do notsatisfy specifications, or players cannot arrive at the goal
from the start by passing all thecheckpoints.
Input
The input is to be given in the followingformat, from the standard input.
W H
Row1
Row2
...
RowH
The first row is to describe the width andthe height of the orienteering map, sectioned by a space.
From the second row, map information is tobe given for exactly the same number of rows as the
height.
Each row contains exactly the same numberof letters as the width.
See “Specification” for details of thesymbols contained in the map.
Output
Output into the standard output, and put areturn.
**DO NOT forget to delete debug outputsbefore submission** .
Implementation
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>using namespace std;#define inf (1<<29)const int maxn = 18;int value[maxn][(1<<maxn)];bool state[maxn][(1<<maxn)];int n , m , cnt;char ch[111][111];int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};struct Node { int id , x , y;}p[110];struct node { int x , y; node () {} node (int x,int y) : x(x) , y(y) {};};int Id[110][110];int mp[110][110];bool vis[110][110];int gg[33][33];int ss , tt;bool inmap(int x, int y) { return x >= 0 && x < n && y >= 0 && y < m;}queue <node> q;void bfs(int id) { while(!q.empty()) q.pop(); int x = p[id].x , y = p[id].y; memset(mp, -1, sizeof(mp)); memset(vis, false, sizeof(vis)); mp[x][y] = 0; node u = node(x , y); q.push(u); while(!q.empty()) { u = q.front(); q.pop(); vis[u.x][u.y] = false; for(int i=0;i<4;i++) { int x = u.x + dir[i][0]; int y = u.y + dir[i][1]; if(!inmap(x, y)) continue; if(mp[x][y] == -1 || mp[x][y] > mp[u.x][u.y]+1) { mp[x][y] = mp[u.x][u.y] + 1; if(!vis[x][y]) { vis[x][y] = true; node v = node(x, y); q.push(v); } } } }}void debug() { puts("debug"); for(int i=0;i<cnt;i++) { for(int j=0;j<cnt;j++) { printf("%d ", gg[i][j]); } puts(""); }}bool init() { for(int i=0;i<n;i++) scanf("%s" , ch[i]); cnt = 0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(ch[i][j] == '@') { Id[i][j] = cnt; p[cnt].x = i; p[cnt].y = j; p[cnt].id = cnt ++; } ss = cnt ; tt = cnt + 1; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(ch[i][j] == 'S') { Id[i][j] = ss; p[ss].x = i; p[ss].y = j; p[ss].id = ss; } else if(ch[i][j] == 'G') { Id[i][j] = tt; p[tt].x = i; p[tt].y = j; p[tt].id = tt; } } cnt += 2; for(int i=0;i<cnt-1;i++) { bfs(i); for(int j=0;j<cnt;j++) { int x = p[j].x; int y = p[j].y; int diss = mp[x][y]; gg[i][j] = gg[j][i] = diss; if(diss == -1) return false; } } //debug(); return true;}int dfs(int pos, int sta) { if(state[pos][sta]) return value[pos][sta]; state[pos][sta] = true; int cc = 0; for(int i=0;i<cnt-2;i++) if((1<<i) & sta) cc ++; //cout << "cc is " << cc << endl; if(cc == 1) return (value[pos][sta] = gg[ss][pos]); value[pos][sta] = inf; int sta_before = sta ^ (1<<pos); for(int i=0;i<cnt-2;i++) { int tmp = inf; //if(gg[i][pos] < 0) cout << "hello world!!!!!!!!!!!!!!!!!" << endl; if(sta_before & (1<<i)) tmp = dfs(i, sta_before) + gg[i][pos]; if(tmp < value[pos][sta]) value[pos][sta] = tmp; } return value[pos][sta];}void debug2() { puts("debug2"); for(int i=0;i<cnt-2;i++) cout << "haha : " << dfs(i, 1<<(i)) << endl; puts("end of debug2"); for(int i=0;i<4;i++) { for(int j=14;j<16;j++) { //int j = 14; if((1<<i) & j) printf("%d : %d : %d\n" , i , j , dfs(i, j)); } }}int main() { while(scanf("%d%d" , &n, &m) != EOF) { if(!init()) { puts("-1"); continue; } if(cnt - 2 == 0) { int ans = gg[ss][tt]; printf("%d\n" , ans); } //cout << "cnt is " << cnt <<endl; //cout << "check : " << (1<<(cnt-2))-1 << endl; memset(state, false, sizeof(state)); int ans = inf; for(int i=0;i<cnt-2;i++) { int tmp = dfs(i, (1<<(cnt-2))-1) + gg[i][tt]; //cout << "tmp : " << tmp << endl; if(tmp < ans) ans = tmp; } //for(int i=0;i<cnt-2;i++) printf("%d\n" , ans); //debug2(); } return 0;}/*#########@....G###.##@###..@..S##@.....#########*/
- 一道用到二进制位加记忆化搜索的dp题
- poj3252 数位dp(所有比n小的二进制位0的个数不少于1的个数)记忆化搜索
- HDU 3652 记忆化搜索加 多维数位dp 模板
- 百练+dp or DFS+dp就是记忆化搜索,加个数组记忆
- dp记忆化搜索
- 记忆化搜索,dp
- 记忆化搜索DP
- 记忆化搜索,以及其他的dp
- 数位DP的记忆化搜索形式
- 浅谈数位DP的记忆化搜索
- uva242, 完全背包||记忆化搜索,(类似广工校赛的一道题)
- HDU 1978 How many ways(第一道记忆化搜索+DP)
- poj1088 dp+记忆化搜索
- UVA103 DP记忆化搜索
- poj1664 dp记忆化搜索
- DP/记忆化搜索+set
- [dp+记忆化搜索]uva10626
- HDU3779Railroad DP 记忆化搜索
- 一、ROS系统介绍及安装
- Windows作业
- TextField.leftView
- 用jq如何把一个机构树拦腰分成两列。
- Tint Color的理解和APP简单的主题化
- 一道用到二进制位加记忆化搜索的dp题
- 编译成ASCII码,加上_T()或TEXT()变成UNICODE
- 二叉树学习之哈弗曼编码
- HDU__A - How Many Tables(第一天)
- java PLAY框架学习笔记--入门
- Token验证失败
- UITextField可以设置右边和右边的图片
- Java中访问权限控制
- iOS弹键盘、收键盘