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;
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。