zoj 2110 Tempter of the Bone(奇偶剪枝法)

题目链接:点击打开链接

最开始以为是在t秒内是否能到达door,写成了bfs,一直WA,后面发现是dfs后一直T...,在下实在不知道怎么剪枝了,就去百度了一发,然后发现了这个

int dis;                              
        dis=(T-time)-(fabs(x-xd)+fabs(y-yd));    // =剩下的时间-无障碍物下的最短路径 
        if(dis<0||dis%2)  return;                //小于0或为奇数就剪掉 
奇偶剪枝,出奇的好用,直接一发AC。至于原理嘛


 要从S走到D,忽略障碍显然最短路径长度是10,而我们把表格用1,0相间填满,易得无论怎么走,1->00->1一定是奇数步,0->01->1一定是偶数步。

假设还剩13秒,我们先走掉最短路径的10秒,到达的地方一定是0,再走剩下的3秒,到达的一定是1,所以走不到D,这时候就可以直接剪掉。起点是1,终点是0的情况也是一样的,所以只有当剩下的时间-最短路径是偶数时,才可能在剩下的时间刚好走到终点。

奇偶剪枝详见百度百科:点击打开链接

附上完整代码

#include<iostream>   
#include<algorithm>  
#include<string.h>  
#include<string>   
#include<stdio.h>  
#include<stdlib.h>  
#include<math.h>
using namespace std;  
#define CRL(a,b) memset(a,b,sizeof(a))    
typedef unsigned long long LL;  
typedef  long long ll;

char map[10][10];
bool book[10][10];

int move_y[4]={0,1,0,-1},
    move_x[4]={1,0,-1,0},m,n,T,X,Y,Find=0,xd,yd;

void create(int n,int m)
{
	for(int i=0;i<n;i++)  
            scanf("%s",map[i]);  
          
        for(int i=0;i<n;i++){  
            for(int j=0;j<m;j++){  
                if(map[i][j]=='S')  {X=i;Y=j;}  
                if(map[i][j]=='D')  {xd=i;yd=j;}  
            }  
        }
} 

void dfs(int x,int y,int time)
{
     if(map[x][y]=='D'&&time==T)
	 	{
	 		cout<<"YES\n";
	 		Find=1;
	 		return;
		 }
		 
		int dis;                              //奇偶剪枝:判断在剩余时间里能否走到终点,不是充要条件 
        dis=(T-time)-(fabs(x-xd)+fabs(y-yd));    // =剩下的时间-无障碍物下的最短路径 
        if(dis<0||dis%2)  return;                //小于0或为奇数就剪掉 
	
	for(int i=0;i<4;i++)
	 {
	 	int next_x=x+move_x[i];
	 	int next_y=y+move_y[i];
	 	if(next_x<0||next_y<0||next_x>n-1||next_y>m-1||map[next_x][next_y]=='X'||book[next_x][next_y])
	 	 continue;
	 	else
	 	{
	 		book[next_x][next_y]=1;
	 	     dfs(next_x,next_y,time+1);
	 	     if(Find)  return;
	 	    book[next_x][next_y]=0;
		 }
	 }
	 return;
}
 
int main()	         
{
	  while(~scanf("%d%d%d",&n,&m,&T))
	  {  
        if(n==0&&m==0&&T==0)  break; 
	   	Find=0;
		create(n,m);
		CRL(book,0);
		book[X][Y]=1;
		dfs(X,Y,0);
		if(!Find)
		 cout<<"NO\n";
	    }
	return 0;
}
还有一开始写错了的bfs,在t秒内能否到达door(未找题测试,仅供参考)

扫描二维码关注公众号,回复: 1804170 查看本文章
#include<iostream>   
#include<algorithm>  
#include<string.h>  
#include<string>   
#include<stdio.h>  
#include<stdlib.h>  
#include<math.h>
using namespace std;  
#define CRL(a) memset(a,'X',sizeof(a))    
typedef unsigned long long LL;  
typedef  long long ll;

struct node
{
	int x,y,pre;
}way[50];

int move_y[4]={0,1,0,-1},
    move_x[4]={1,0,-1,0},m,n,T;

char map[10][10];

void create(int n,int m)
{
	getchar();
	CRL(map);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%c",&map[i][j]);
			if(map[i][j]=='S')
			{
				way[1].x=j;
				way[1].y=i;
				way[1].pre=0;
			}
		}
		getchar();//吸收回车 
	}	 
}

void bfs()
{
	int X,Y,front=1,rear=1,m=0,n=1,time=0;
	while(1)
	{
		for(int i=0;i<4;i++)
		{
			X=way[front].x+move_x[i];
		    Y=way[front].y+move_y[i];
			if(map[X][Y]=='D')
			{
				cout<<"YES\n";
				return;
			}
			 
		    if(map[X][Y]=='.')
		    {
		    	rear++;m++;          
		    	way[rear].x=X;
		    	way[rear].y=Y;
				map[X][Y]='@';		//用'@'只是调试时看着方便		 
			}
		 }
		front++;
		if(--n==0)
		{
			if(m==0)                //找不到一条新的路了 
			 {
				cout<<"NO\n"; return;
			 }
			else
			 {
			  time++;
			   if(time>=T)         //时间到 
			    {
			    	cout<<"NO\n";
			    	return;
				}
			  n=m;
			  m=0;
			 } 
		} 
	}
	
}
  
int main()
{
	while(cin>>n>>m>>T&&(n||m||T))
	{
		create(n,m);
		bfs();
	}
	return 0;
}



猜你喜欢

转载自blog.csdn.net/x_armin/article/details/79059423