hdu 1728 逃离迷宫 剪枝DFS
2017-10-31 19:48
465 查看
有两点需要注意。
第一点是转弯问题,准备一个数组来存放到达每个点最小的转弯数。
第二点就是剪枝了
剪枝1:如果求出来了,直接return
剪枝2:如果当前已经大于最大转弯数了,直接return
剪枝3:第二次到达某个点时,如果转弯数大于之前到达的一次,直接return
剪枝4:同样第二次到达某点,如果方向不一样我们还要+1,判断+1之后是否大于之前到达的那一次,如果大于了直接return
#include <stdio.h>
#include <string.h>
#include <math.h>
#define Max 999999
#include <algorithm>
using namespace std;
struct point
{
int x,y;
}s[20000];
char map[110][110];
int turn[110][110];
int n,m,x2,y2,ok,k;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
void dfs(int x,int y,int dir)
{
int i,xx,yy;
if(x==x2 && y==y2 && turn[x][y]<=k)
{
ok=1;
return ;
}
if(turn[x][y]>k) //剪枝1:如果超出步数,return
return ;
if(x!=x2 && y!=y2 && turn[x][y]==k) //剪枝2:如果没有步数了,还没到。return
return ;
for(i=0;i<4;i++)
{
xx=x+dx[i];
yy=y+dy[i];
if(xx<=0 || yy<=0 || xx>m || yy>n || map[xx][yy]=='*')
continue;
if(turn[xx][yy]<turn[x][y]) //剪枝3:如果已经去过了,转的比之前的多,直接return。
continue;
if(dir!=-1 && i!=dir && turn[xx][yy]<turn[x][y]+1) //如果想过去我们还要转一次玩。同剪枝3再判断一次
continue;
if(dir!=-1 && i!=dir)
turn[xx][yy]=turn[x][y]+1;
else
turn[xx][yy]=turn[x][y];
map[xx][yy]='*';
dfs(xx,yy,i);
map[xx][yy]='.';
if(ok)
return ;
}
}
int main()
{
int i,j,t,x1,y1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf(" %c",&map[i][j]);
scanf("%d%d%d%d%d",&k,&y1,&x1,&y2,&x2);
memset(turn,Max,sizeof(turn));
ok=0;
turn[x1][y1]=0;
dfs(x1,y1,-1);
if(ok)
printf("yes\n");
else
printf("no\n");
}
return 0;
}
第一点是转弯问题,准备一个数组来存放到达每个点最小的转弯数。
第二点就是剪枝了
剪枝1:如果求出来了,直接return
剪枝2:如果当前已经大于最大转弯数了,直接return
剪枝3:第二次到达某个点时,如果转弯数大于之前到达的一次,直接return
剪枝4:同样第二次到达某点,如果方向不一样我们还要+1,判断+1之后是否大于之前到达的那一次,如果大于了直接return
#include <stdio.h>
#include <string.h>
#include <math.h>
#define Max 999999
#include <algorithm>
using namespace std;
struct point
{
int x,y;
}s[20000];
char map[110][110];
int turn[110][110];
int n,m,x2,y2,ok,k;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
void dfs(int x,int y,int dir)
{
int i,xx,yy;
if(x==x2 && y==y2 && turn[x][y]<=k)
{
ok=1;
return ;
}
if(turn[x][y]>k) //剪枝1:如果超出步数,return
return ;
if(x!=x2 && y!=y2 && turn[x][y]==k) //剪枝2:如果没有步数了,还没到。return
return ;
for(i=0;i<4;i++)
{
xx=x+dx[i];
yy=y+dy[i];
if(xx<=0 || yy<=0 || xx>m || yy>n || map[xx][yy]=='*')
continue;
if(turn[xx][yy]<turn[x][y]) //剪枝3:如果已经去过了,转的比之前的多,直接return。
continue;
if(dir!=-1 && i!=dir && turn[xx][yy]<turn[x][y]+1) //如果想过去我们还要转一次玩。同剪枝3再判断一次
continue;
if(dir!=-1 && i!=dir)
turn[xx][yy]=turn[x][y]+1;
else
turn[xx][yy]=turn[x][y];
map[xx][yy]='*';
dfs(xx,yy,i);
map[xx][yy]='.';
if(ok)
return ;
}
}
int main()
{
int i,j,t,x1,y1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf(" %c",&map[i][j]);
scanf("%d%d%d%d%d",&k,&y1,&x1,&y2,&x2);
memset(turn,Max,sizeof(turn));
ok=0;
turn[x1][y1]=0;
dfs(x1,y1,-1);
if(ok)
printf("yes\n");
else
printf("no\n");
}
return 0;
}
相关文章推荐
- 搜索专题(DFS&&BFS&&剪枝)HDU 1728-逃离迷宫
- hdu 1728:逃离迷宫(DFS,剪枝)
- HDU 1728 逃离迷宫 单方向BFS 或者DFS加剪枝
- hdu 1728 逃离迷宫(DFS)
- 1728 hdu 逃离迷宫(DFS)
- HDU-1728 逃离迷宫(DFS)
- HDU 1728 逃离迷宫(DFS||BFS)
- HDU 1728 逃离迷宫(dfs或bfs+剪枝)
- HDU 1728 逃离迷宫(BFS+DFS)
- HDU - 1728 - 逃离迷宫(dfs)
- hdu 1728 逃离迷宫 (论DFS思想在BFS中的应用)
- hdu-1728逃离迷宫(dfs 求拐弯次数)
- hdu 1728 逃离迷宫(dfs)
- HDU 1728逃离迷宫(简单dfs)
- hdu 1728 逃离迷宫(dFS+优先队列)
- HDU 1728 逃离迷宫(DFS经典题,比赛手残写废题)
- HDOJ/HDU 1728 逃离迷宫 DFS 深度优先搜素
- hdu 1728 逃离迷宫 (DFS+转弯数剪枝)
- HDU1728 逃离迷宫 DFS
- HDU 1728逃离迷宫(DFS或者BFS)