用到的算法:DFS+剪枝
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
题意:
由起始位置出发t秒时能否到达出口。每秒可以从当前位置沿上、下、左、右四个方向移动一步,不过每个位置最多只能走一遍
思路:
基础搜索题,dfs
dfs的思想是比较直观的,如果不加以剪枝这题的所有状态为4^(n*m),很小的规模(本题中0<n,m<7)就足以TLE
下面介绍本题中我用到的剪枝策略:
1、深度剪枝,如果当前搜索的深度(即时间)已经超过t,则中止搜索;
2、如果迷宫中所以的非'X'数目小与t,则直接输出结果为"NO";
3、如果已经搜索到结果,中止所有的搜索;
4、奇偶性剪枝,详细介绍如下:
把map看成这样:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
从 0 的格子走一步,必然为 1 的格子
从 1 的格子走一步,必然为 0 的格子
规律:
0->1或1->0 必然是奇数步
0->0或1->1 必然是偶数步
结论:
当遇到从 0 走向 0 但是要求时间是奇数的,
或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达!
5、如果从当前的位置到目标位置所需的理论上的最少时间大于了当前剩余的时间,直接判断为不可到达
#include<iostream>
using namespace std;
char maze[7][7];
int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};//四个方向
int sx,sy,tx,ty; //sx,sy为初始位置,tx,ty为目标位置
int r,c,t;//r和c表示迷宫的长和宽,t表示规定到达的时间
bool out; //out为1表示走出迷宫
bool judge(int x,int y)
{
return (x>=0 && x<r && y>=0 && y<c && maze[x][y]!='X');
}
void dfs(int deep,int curx,int cury)
{
if(deep==t && curx==tx && cury==ty) out=1;
if(deep>t||out) return ; //剪枝 1、3
if(t-deep<abs(curx-tx)+abs(cury-ty)) return; //剪枝 5
if((t-deep)%2!=(abs(curx-tx)+abs(cury-ty))%2) return ; //剪枝 4
for(int i=0;i<4;i++)
{
int x,y;
x=curx+dx[i];
y=cury+dy[i];
if(judge(x,y))
{
maze[x][y]='X';
dfs(deep+1,x,y);
maze[x][y]='.';//这里是回溯的精华
}
}
}
int main()
{
while(cin>>r>>c>>t,r||c||t)
{
int cnt=0;
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
{
cin>>maze[i][j];
if(maze[i][j]!='X') cnt++;
if(maze[i][j]=='S')
sx=i,sy=j;
if(maze[i][j]=='D')
tx=i,ty=j;
}
maze[sx][sy]='X';
if(cnt<t)
cout<<"NO"<<endl;//剪枝2
else
{
out=0;
dfs(0,sx,sy);
if(out)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
return 0;
}
转自:
http://blog.csdn.net/once_hnu/article/details/6305935