解题报告:HDU_1813 Escape from Tetris 综合搜索IDA*
2016-07-06 15:35
661 查看
Escape from Tetris
Time Limit: 12000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1206 Accepted Submission(s): 326
[align=left]Problem Description[/align]
由于整日整夜地对着这个棋盘,Lele终于走火入魔。每天一睡觉,他就会梦到自己会被人被扔进一个棋盘中,一直找不到出路,然后从梦中惊醒。久而久之,Lele被搞得精神衰弱。梦境是否会成为现实,谁也说不准,不过不怕一万只怕万一。现在Lele每次看到一个棋盘,都会想象一下自己被关进去以后要如何逃生。
Lele碰到的棋盘都是正方形的,其中有些格子是坏的,不可以走,剩下的都是可以走的。只要一走到棋盘的边沿(最外面的一圈),就算已经逃脱了。Lele梦见自己一定会被扔在一个可以走的格子里,但是不确定具体是哪一个,所以他要做好被扔在任意一个格子的准备。
现在Lele请你帮忙,对于任意一个棋盘,找出一个最短的序列,序列里可以包括"north"(地图里向上),"east"(地图里向右),"south"(地图里向下),"west"(地图里向左),这四个方向命令。不论Lele被扔在棋盘里的哪个好的格子里,都能按这个序列行走逃出棋盘。
逃脱的具体方法是:不论Lele被扔在哪里,Lele按照序列里的方向命令一个一个地走,每个命令走一格,如果走的时候会碰到坏的格子,则忽略这条命令。当然,如果已经逃脱了,就可以不考虑序列中剩下的命令了。
[align=left]Input[/align]
本题目包含多组测试,请处理至文件结束。
每组测试第一行包含一个正整数 N (0<N<9),代表棋盘的大小是 N*N
接下来有N行,每行N个字符代表这个棋盘。
其中0代表该位置是好的,可以走,1代表该位置是坏的,不可以走。
题目数据保证,对于任意一个棋盘,都存在题目中所要求的序列
[align=left]Output[/align]
对于每组数据,输出题目所要求的序列,序列中每个元素一行。
如果存在两个符合要求的序列,请输出字典序最小的那个序列。
两个测试之间请用一个空行隔开。
[align=left]Sample Input[/align]
4
1101
0001
1100
1001
[align=left]Sample Output[/align]
east
north
[align=left]Author[/align]
linle
[align=left]Source[/align]
HDOJ 2007 Summer Exercise(2)
[align=left]Recommend[/align]
lcy
Statistic | Submit | Discuss
|
Note
题意:
一个人被困在迷宫除边界的某个位置,先让你求一个最短的字典序最小的行走方向的序列,使得无论在迷宫的哪个位置,都能依靠这个序列走出去(也就是走到不是墙的边界上)。如果下一步行走方向的位置是墙,那么这一步不执行。
思路:
先以所有出口(不是墙的边界)为起点进行BFS得出每个可行位置的下界步数作为评估函数,然后迭代加深序列长度,DFS序列求解,一个细节是可以把执行了前几步后的迷宫地图作为参数传入下一步这样节省大量重复运算。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> const int X[4]={0,-1,1,0}; const int Y[4]={1,0,0,-1}; using namespace std; #define fi first #define se second bool mp[12][12]; int str[1000]; int n,m,step; pair<int,int>Q[100]; int h[20][20]; queue<pair<int,int> >QQ; inline void get_h(){ m=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(mp[i][j]){ if(i==1||j==1||i==n||j==n){ h[i][j] = 0; QQ.push(make_pair(i,j)); } else { h[i][j] = 1000000; Q[m++]=make_pair(i,j); } } } } } inline void bfs(){ while(!QQ.empty()){ int x = QQ.front().fi; int y = QQ.front().se; QQ.pop(); for(int k=0;k<4;k++){ int a = x + X[k]; int b = y + Y[k]; if(!a||!b||a>n||b>n)continue; if(mp[a][b]){ if(h[x][y]+1<h[a][b]){ h[a][b] = h[x][y]+1; QQ.push(make_pair(a,b)); } } } }for(int i=0;i<m;i++){ int& x = Q[i].fi ; int& y = Q[i].se ; step = max(step,h[x][y]); } } inline bool check(bool s[12][12]){ for(int i=2;i<n;i++){ for(int j=2;j<n;j++){ if(s[i][j]){ return false ; } } }return true; } bool dfs(int step,int lim,bool m[12][12]){ bool nxt[12][12]; for(int k=0;k<4;k++){bool ok = true; memset(nxt,0,sizeof(nxt)); str[step]=k; for(int i=2;i<n;i++){ for(int j=2;j<n;j++){ if(m[i][j]){ int a = i + X[k],b = j + Y[k]; if(mp[a][b]){ if(!nxt[a][b]&&h[a][b]>lim-step+1){ i = n; j = n; ok = false ; break; } nxt[a][b] = true; }else { if(!nxt[i][j]&&h[i][j]>lim-step+1){ i = n; j = n; ok = false ; break; } nxt[i][j] = true; } } } } if(!ok)continue; if(step==lim&&check(nxt)){ return true; }else if(step!=lim){ if(dfs(step+1,lim,nxt)){ return true; } } }return false ; } int main() { int time = 0; while(scanf("%d",&n)==1){ step=1; for(int i=1;i<=n;i++){ char s[12]; scanf("%s",s); for(int j=0;j<n;j++){ mp[i][j+1] = (s[j]-'0')^1; } } get_h(); bfs(); if(time++){ printf("\n"); } if(check(mp)){ continue; } for(;;step++){ if(dfs(1,step,mp)){ break; } } for(int i=1;i<=step;i++){ if(str[i]==0){ printf("east\n"); }else if(str[i]==1){ printf("north\n"); }else if(str[i]==2){ printf("south\n"); }else { printf("west\n"); } } }return 0 ; }
相关文章推荐
- 11个实用但你可能不知道的Python程序库
- java servlet与sql server
- maven学习笔记-基础
- (document).height()与$(window).height()
- qemu-kvm部分流程/源代码分析
- Android 源码编译详解【一】:服务器硬件配置及机型推荐-2016/06
- 如何判断栈、堆的增长方向?
- jQuery操作iframe中js函数的方法小结
- 剑指offer——二叉树的下一个节点
- LINQ to Entities 不识别方法"System.String ToString()"
- java链表之--单向循环链表
- 二维数组中查找一个数是否存在
- 关于android开机速度性能方面
- UNIX_C 链表贪吃蛇游戏_吃苹果可生长代码——<.h头文件>
- ContentType设置的内容
- js中Window 对象及其的方法
- swift计算 switch case
- final关键字
- HDU 2602 Bone Collector
- 动态规划 解决打印所有和为s的连续整数序列 剑指offer 之 面试题41_2