杭电OJ 1010, 从非递归的DFS 到 剪枝

今天敲了一波杭电的1010,面对迷宫一类的题目,我留在印象中的就是用栈来解决。后来查阅了一下网上的解决方法,发现用的是DFS+剪枝算法,当然,就我的代码而言,单单采用栈来敲,是不能AC的。


从某种程度上来说,我的代码就是采用栈和一定的数据结构实现了递归的DFS所具备的功能。


废话不多说,先上代码





//每个位置的探索方向按顺序依次是(左(L),上(T),右(R),下(B))
#include <iostream>
#include <stack>
#include <math.h>
using namespace std;

class Point   //定义点的数据结构
{
public:
	char prop;   //这个点上承载的是什么(D或者X或者.)
	char currentDirection;   //当前要探索的方向
	bool stakeState;    //目前在不在栈里面
	int x,y;
	Point()
	{
		x=0;
		y=0;
		prop='N';
		currentDirection='L';
		stakeState=false;
	}
};


int main()
{
	Point A[100][100]={};
	stack<Point> B;
	int row=0;
	int column=0;
	int time=0;
	int sx,sy;  //初始点
	int ex,ey;  //终点
	int wall=0; //X的数量
	bool flag=false;
	std::cin>>row>>column>>time;
	while(!(row==0&&column==0&&time==0))
	{
		flag=false;
		wall=0;
		for(int i=0;i<row;i++)
		{
			for(int j=0;j<column;j++)
			{
				std::cin>>A[i][j].prop;
				A[i][j].x=i;
				A[i][j].y=j;
				A[i][j].currentDirection='L';
				A[i][j].stakeState=false;
				if(A[i][j].prop=='S')
				{
					sx=i;
					sy=j;
				}
				else if(A[i][j].prop=='D')
				{
					ex=i;
					ey=j;
				}
				else if(A[i][j].prop=='X')
					wall++;
			}
		}
		//剪枝,剪短程序运行时间
		if(((time-(abs(sx-ex)+abs(sy-ey)))%2!=0)||(time-(abs(sx-ex)+abs(sy-ey))<0)||row*column-wall<=time)
		{
			cout<<"NO"<<endl;
			std::cin>>row>>column>>time;
			continue;
		}



		while(1)	
		{
			if(A[sx][sy].currentDirection=='L')
			{
				//下一个位置不能是越界、或者已经走过的位置(进栈了就是之间走过的)、或者障碍
				if(sy-1>=0&&A[sx][sy-1].stakeState==false&&A[sx][sy-1].prop!='X')  
				{
					time--;  //用掉1s走了一步
					if(A[sx][sy-1].prop=='D'&&time==0) //符合逃脱条件
					{
						flag=true;
						break;
					}
					A[sx][sy].currentDirection='T';  //设置该位置下一个待探索的方向
					A[sx][sy].stakeState=true;  //进栈
					B.push(A[sx][sy]);
					sy=sy-1;     //更新狗的当前位置
				}
				else
					A[sx][sy].currentDirection='T';   //如果前面的条件不符合,直接探索当前位置的下一个方向
			}
			if(A[sx][sy].currentDirection=='T')
			{
				if(sx-1>=0&&A[sx-1][sy].stakeState==false&&A[sx-1][sy].prop!='X')
				{
					time--;
					if(A[sx-1][sy].prop=='D'&&time==0)
					{
						flag=true;
						break;	
					}
					A[sx][sy].currentDirection='R';
					A[sx][sy].stakeState=true;
					B.push(A[sx][sy]);
					sx=sx-1;
				}
				else
					A[sx][sy].currentDirection='R';
			}
			if(A[sx][sy].currentDirection=='R')
			{
				if(sy+1<column&&A[sx][sy+1].stakeState==false&&A[sx][sy+1].prop!='X')
				{
					time--;
					if(A[sx][sy+1].prop=='D'&&time==0)
					{
						flag=true;
						break;
					}
					A[sx][sy].currentDirection='B';
					A[sx][sy].stakeState=true;
					B.push(A[sx][sy]);
					sy=sy+1;
				}
				else 
					A[sx][sy].currentDirection='B';
			}
		    if(A[sx][sy].currentDirection=='B')
			{
				if(sx+1<row&&A[sx+1][sy].stakeState==false&&A[sx+1][sy].prop!='X')
				{
					time--;
					if(A[sx+1][sy].prop=='D'&&time==0)
					{
						flag=true;
						break;
					}
					A[sx][sy].currentDirection='Q';   //Q表示4个可能的方向都已经被探索完毕
					A[sx][sy].stakeState=true;
					B.push(A[sx][sy]);
					sx=sx+1;
				}
				else
					A[sx][sy].currentDirection='Q';
			}
			//弹栈的条件(退回到上一个位置):当前位置没有可以探索的方向了或者时间用完当时没找到门(路没找对)或者
			//找到门了时间不对门没开(还是路不对)

			if(A[sx][sy].currentDirection=='Q'||(time==0)&&(A[sx][sy].prop!='D')||(time!=0)&&(A[sx][sy].prop=='D'))
			{
				if(A[sx][sy].prop=='S')  //所有可能方向都试遍了
				{
					flag=false;
					break;   //出不去了
				}
				time++;//时间回退
				A[sx][sy].currentDirection='L';  //每个位置的可探索方向被重置(就是少了这个让我卡了好久)
				A[B.top().x][B.top().y].stakeState=false;
				sx=B.top().x;
				sy=B.top().y;
				B.pop();
			}
		}
		if(flag==false)
			cout<<"NO"<<endl;
		else
			cout<<"YES"<<endl;
		cin>>row>>column>>time;
	}
}

			














	
		



剪枝的问题不解决的话,是不能AC的!

剪枝问题在下属博客中讲的相当清楚:

http://www.cnblogs.com/newpanderking/archive/2012/10/09/2716984.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值