鸣人和佐助(老婆)

传送门鸣人和佐助
鸣人和佐助(老婆)_第1张图片
深搜法:在图上深搜,需要剪枝
细节都在注释里了

#include 
#include 
#include  
using namespace std;

int M,N,T;
char G[210][210];
int visited[210][210];
int minTime = 1 << 30;
int curTime = 0;

int narutox,narutoy;
int sasukex,sasukey;	
void Dfs(int x,int y);

int minT[210][210][20];//minT[i][j][k]表示剩余k查克拉 从起点到G[i][j]的最小时间 
int DIRECTION[4][2] = {
	{0,-1},
	{0,1},
	{-1,0},
	{1,0}
};

int main()
{
	cin >> M >> N >> T;
	
	for(int i=0;i<M;++i)
	{
		for(int j=0;j<N;++j)
		{
			cin >> G[i][j];
			if(G[i][j] == '@')
			{
				narutox = i;
				narutoy = j;
			}
			else if(G[i][j] == '+')
			{
				sasukex = i;
				sasukey = j;
			}
			for(int k=0;k<20;++k)
				minT[i][j][k] = 1<<30;
		}
	}
	
	memset(visited,0,sizeof(visited));
	visited[narutox][narutoy] = 1;
	Dfs(narutox,narutoy);
	
	if(minTime < (1<<30))
		cout << minTime << endl;
	else
		cout << "-1" << endl;
		
	return 0;
}

void Dfs(int x,int y)
{
	if(G[x][y] == '+')
	{
		minTime = min(minTime,curTime);
		return ;
	}
	
	for(int i=0;i<4;++i)
	{
		int x1 = x+DIRECTION[i][0];
		int y1 = y+DIRECTION[i][1];
		
		if(x1 < 0 || x1 >= M || y1 < 0 || y1 >= N)
			continue;
		
		if(!visited[x1][y1])
		{
			//只可能是通路或大蛇丸手下 
			
			//剪枝 
			if(G[x1][y1] == '#' && T==0)
				continue;	
//			if(curTime + 1 >= minTime) // 不好 因为只会剪掉 curTime=minTime-1 
//				continue;
			if(curTime + 1+abs(sasukex-x1)+abs(sasukey-y1) > minTime)
				continue;
			if(G[x1][y1] == '#' && curTime+1 >= minT[x1][y1][T-1])
				continue;	
			if(G[x1][y1] == '*' && curTime+1 >= minT[x1][y1][T])
				continue;
					
			//更新路径参数
			if(G[x1][y1] == '#' && T>0)
				--T;
			curTime++;
			minT[x1][y1][T] = curTime;
			visited[x1][y1] = 1;
			
			//cout <<"("<" <<"("<
			Dfs(x1,y1);
			
			//重置路径参数
			curTime--;
			visited[x1][y1] = 0;
			if(G[x1][y1] == '#')
				++T;
		}
	}
}

没有更好的剪枝方案时,如何进一步提升速度?

根据剪枝的特点,如果我们能很早的找到那个最优路径(最优解),那么我们就可以用它剪去更多的无用分枝。那么,如何才能更早的找到那个最优路径(最优解)呢?
首先,我们在进行深搜时,每次是沿着相邻节点去扩展路径的,本题中,每个节点可以往上下左右四个方向扩展。
那么,对于这么一种情况:
鸣人和佐助(老婆)_第2张图片
我们有理由认为(大概率),最优路径的方向是在右下角,因此我们可以优先让节点s的扩展方向为右、下,也就是重置方向偏移数组DIRECTION[4][2]={右偏移,下偏移,左偏移,上偏移}。
我们让每个节点在扩展的时候都有这么一个寻路偏好,那么深搜寻路时我们就有较大把握尽快找到那条最优路径,而不会去走很多多余的路
然而很多问题中这种寻路偏好没有本题这么好设定

你可能感兴趣的:(剪枝,算法,dfs)