4 4 5S.X...X...XD....3 4 5S.X...X....D0 0 0
NOYES
分析:
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
解题思路:这道题,要用到剪枝搜索来做,否则会超时。剪掉的条件是,如果可走地板数目小于给定的时间,绝对不可能得救。还有就是狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门,也不可能得救,剪掉这两种情况后。就用DFS来做。从起点出发,DFS周围的路,走过的路就标记为不可走,一只搜索下去,如果是一条不归路(就是活不了啦)就回溯,把可能的路都搜索一遍过去,看看是否有可行方案。
源码:(TLE)——未剪枝、未加优化
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std; int n,m,t; char map[10][10]; int flag; int di,dj,wall; int i,j,si,sj; int to[4][2] = {-1,0,1,0,0,-1,0,1}; void dfs(int si,int sj,int cnt)//深搜 { if(si>=n || sj>=m || si<0 || sj < 0)//出界 return ; if(cnt == t && si == di && sj == dj)//到达终点 flag = 1; if(flag) return ; for(int i = 0; i<4; i++) { int nextx=si+to[i][0]; int nexty=sj+to[i][1]; if(nextx>=0&&nextx<m&&nexty>=0&&nexty<n&&map[nextx][nexty]!='X') { map[nextx][nexty]='X';//走过的地方变为墙 dfs(nextx,nexty,cnt+1); map[nextx][nexty]='.';//迷宫还原,以便下次广搜 } } return ; } int main() { while(scanf("%d%d%d",&n,&m,&t)&&(n!=0||m!=0||t!=0)) { getchar(); wall = 0; for(i = 0; i<n; i++) for(j = 0; j<m; j++) { cin>>map[i][j]; if(map[i][j] == 'S') { si = i; sj = j; //标记起点 } else if(map[i][j] == 'D') { di = i; dj = j; //标记终点 } else if(map[i][j] == 'X') wall++;//对“#计数” } flag = 0; map[si][sj] = 'X';//出发点是不可能再走的了,变为墙 dfs(si,sj,0); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; } 剪枝优化后——Accept [cpp] view plaincopyprint? #include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std; int n,m,t; char map[10][10]; int flag; int di,dj,wall; int i,j,si,sj; int to[4][2] = {-1,0,1,0,0,-1,0,1}; void dfs(int si,int sj,int cnt)//深搜 { if(si>=n || sj>=m || si<0 || sj < 0)//出界 return ; if(cnt == t && si == di && sj == dj)//到达终点 flag = 1; if(flag) return ; for(int i = 0; i<4; i++) { int nextx=si+to[i][0]; int nexty=sj+to[i][1]; if(nextx>=0&&nextx<m&&nexty>=0&&nexty<n&&map[nextx][nexty]!='X') { map[nextx][nexty]='X';//走过的地方变为墙 dfs(nextx,nexty,cnt+1); map[nextx][nexty]='.';//迷宫还原,以便下次广搜 } } return ; } int main() { while(scanf("%d%d%d",&n,&m,&t)&&(n!=0||m!=0||t!=0)) { getchar(); wall = 0; for(i = 0; i<n; i++) for(j = 0; j<m; j++) { cin>>map[i][j]; if(map[i][j] == 'S') { si = i; sj = j; //标记起点 } else if(map[i][j] == 'D') { di = i; dj = j; //标记终点 } else if(map[i][j] == 'X') wall++;//对“#计数” } if(n*m-wall<=t||abs(si-di)+abs(sj-dj)>t)//t是代表要走的步数,步数加墙数必须小于总格子数的,因为所有格子中还包括了S和D,这是剪枝 { printf("NO\n"); continue; //abs(si-ei)+abs(sj-ej)为起点到终点的最短步数 } if((abs(si-di)+abs(sj-dj))%2!=(t%2)) { //狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门 printf("NO\n"); continue; } flag = 0; map[si][sj] = 'X';//出发点是不可能再走的了,变为墙 dfs(si,sj,0); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; } 以下代码也能通过,证明,此题主要是奇偶剪枝: [cpp] view plaincopyprint? #include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std; int n,m,t; char map[10][10]; int flag; int di,dj,wall; int i,j,si,sj; int to[4][2] = {-1,0,1,0,0,-1,0,1}; void dfs(int si,int sj,int cnt) //深搜 { if(si>=n || sj>=m || si<0 || sj < 0) //出界 return ; if(cnt == t && si == di && sj == dj) //到达终点 flag = 1; if(flag) return ; for(int i = 0; i<4; i++) { int nextx=si+to[i][0]; int nexty=sj+to[i][1]; if(nextx>=0&&nextx<m&&nexty>=0&&nexty<n&&map[nextx][nexty]!='X') { map[nextx][nexty]='X';//走过的地方变为墙 dfs(nextx,nexty,cnt+1); map[nextx][nexty]='.';//迷宫还原,以便下次广搜 } } return ; } int main() { while(scanf("%d%d%d",&n,&m,&t)&&(n!=0||m!=0||t!=0)) { getchar(); wall = 0; for(i = 0; i<n; i++) for(j = 0; j<m; j++) { cin>>map[i][j]; if(map[i][j] == 'S') { si = i; sj = j; //标记起点 } else if(map[i][j] == 'D') { di = i; dj = j; //标记终点 } else if(map[i][j] == 'X') wall++;//对“#计数” } if((abs(si-di)+abs(sj-dj))%2!=(t%2)) { //狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门 printf("NO\n"); continue; } flag = 0; map[si][sj] = 'X';//出发点是不可能再走的了,变为墙 dfs(si,sj,0); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; } 分享到: 上一篇:世界500百强企业中国的CEO对我们的忠告! 下一篇:最长回文子串 查看评论 暂无评论 您还没有登录,请[登录]或[注册] * 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场 个人资料 bingsanchun 访问:21891次 积分:1768分 排名:第5183名 原创:152篇转载:7篇译文:0篇评论:25条 文章分类 *************ACM**************(0) Data Structure—Stack & Queue(5) Search(6) Data Structure—Linked List(1) Dynamic Programming(2) Greedy(4) String(27) Data Structure—Binary Tree(1) Waters(47) 枚举(4) Deduce(8) BigNums(5) 二分查找(1) Math(21) Moldboard(1) Graph Theory - Union-Find Sets(3) Simulation(1) 堆(1) Graph Theory - Shortest Path(1) STL(3) ACM Skill(2) Others of ACM(1) ************比赛总结************(0) ACM of 2013 省赛(1) *************Java*************(0) acm of java(0) ******computer technology*****(0) computer knowledge(3) Linux(3) IT information(1) ******Personal feelings*******(0) Informal essay(4) Approach to Famous Acmer(1) ACMer感想帖/退役帖(1)
剪枝优化后——Accept
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std; int n,m,t; char map[10][10]; int flag; int di,dj,wall; int i,j,si,sj; int to[4][2] = {-1,0,1,0,0,-1,0,1}; void dfs(int si,int sj,int cnt)//深搜 { if(si>=n || sj>=m || si<0 || sj < 0)//出界 return ; if(cnt == t && si == di && sj == dj)//到达终点 flag = 1; if(flag) return ; for(int i = 0; i<4; i++) { int nextx=si+to[i][0]; int nexty=sj+to[i][1]; if(nextx>=0&&nextx<m&&nexty>=0&&nexty<n&&map[nextx][nexty]!='X') { map[nextx][nexty]='X';//走过的地方变为墙 dfs(nextx,nexty,cnt+1); map[nextx][nexty]='.';//迷宫还原,以便下次广搜 } } return ; } int main() { while(scanf("%d%d%d",&n,&m,&t)&&(n!=0||m!=0||t!=0)) { getchar(); wall = 0; for(i = 0; i<n; i++) for(j = 0; j<m; j++) { cin>>map[i][j]; if(map[i][j] == 'S') { si = i; sj = j; //标记起点 } else if(map[i][j] == 'D') { di = i; dj = j; //标记终点 } else if(map[i][j] == 'X') wall++;//对“#计数” } if(n*m-wall<=t||abs(si-di)+abs(sj-dj)>t)//t是代表要走的步数,步数加墙数必须小于总格子数的,因为所有格子中还包括了S和D,这是剪枝 { printf("NO\n"); continue; //abs(si-ei)+abs(sj-ej)为起点到终点的最短步数 } if((abs(si-di)+abs(sj-dj))%2!=(t%2)) { //狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门 printf("NO\n"); continue; } flag = 0; map[si][sj] = 'X';//出发点是不可能再走的了,变为墙 dfs(si,sj,0); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
以下代码也能通过,证明,此题主要是奇偶剪枝:
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std; int n,m,t; char map[10][10]; int flag; int di,dj,wall; int i,j,si,sj; int to[4][2] = {-1,0,1,0,0,-1,0,1}; void dfs(int si,int sj,int cnt) //深搜 { if(si>=n || sj>=m || si<0 || sj < 0) //出界 return ; if(cnt == t && si == di && sj == dj) //到达终点 flag = 1; if(flag) return ; for(int i = 0; i<4; i++) { int nextx=si+to[i][0]; int nexty=sj+to[i][1]; if(nextx>=0&&nextx<m&&nexty>=0&&nexty<n&&map[nextx][nexty]!='X') { map[nextx][nexty]='X';//走过的地方变为墙 dfs(nextx,nexty,cnt+1); map[nextx][nexty]='.';//迷宫还原,以便下次广搜 } } return ; } int main() { while(scanf("%d%d%d",&n,&m,&t)&&(n!=0||m!=0||t!=0)) { getchar(); wall = 0; for(i = 0; i<n; i++) for(j = 0; j<m; j++) { cin>>map[i][j]; if(map[i][j] == 'S') { si = i; sj = j; //标记起点 } else if(map[i][j] == 'D') { di = i; dj = j; //标记终点 } else if(map[i][j] == 'X') wall++;//对“#计数” } if((abs(si-di)+abs(sj-dj))%2!=(t%2)) { //狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门 printf("NO\n"); continue; } flag = 0; map[si][sj] = 'X';//出发点是不可能再走的了,变为墙 dfs(si,sj,0); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。