HDU 1010-Tempter of the Bone

用到的算法: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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值