您的位置:首页 > 其它

USACO Section 5.4 Betsy's Tour - 搜索剪枝

2012-02-09 02:39 260 查看


这道题我一看就觉得是搜~~~最裸的方法是DFS不断找路径了...我想到的剪枝是说一个路径这么走过去..将一个区域圈出来了.那么继续往后搜怎么也不可能满足题目要求走遍所有点了...所以我就在每次走了一步后..对图进行一次BFS...若得到的连在一起的未拓展面积等于理论上的...才继续往下搜..否则就剪枝,立马return...结果交上去过了6个点..第6个点还是0.1秒过的..结果第七个还是过不去...就要进一步剪枝..我觉得我的思路是没错...但关于如何找出有无被围住的未拓展区域方法显然BFS是很浪费时间的...

还是没想出来...只能学习学习NowCow了...关于NowCow提供的剪枝..我总结下..主要思想就是不走死胡同..

1、当前点左右都是已经点(包括边缘),而上下都是未经点,当前点上下都是已经点(包括边缘),而左右都是未经点..这两种情况下可以判断进入死胡同..立马剪枝..原因画个图就很明显了...例如一个格子左边右边都是遍历过的.上下格子都是没遍历过的.那么显然路径是从这个点的上方或下方某处绕过去从左右两侧的一边到了另一边..而此时无论是向上还是向下走..都不可能再将所有格子遍历到了...

2、首先一个点若要遍历到..显然要从某个方向进去.再从某个方向出来.( 特别注意这里起点和终点例外...)..那么在拓展路径时判断当前点的上下左右4个点...若这四个方向某个点有且仅有一个相邻未拓展格子..那么当前路径的下一步肯定是往这个方向去(假设不去..那么这个点的相邻点就是1了..后面无论怎么遍历都到不了这个点..)...若有多个方向满足这个条件..那么显然当前路径不可能全部满足.. 只能说这样走下去肯定有到不了的区域了...剪枝...而若没有一个方向满足这个条件..那就四个方向枚举的DFS吧~~这里一点要特别注意..虽然说是某个方向的格子未拓展且相邻未拓展格子数为1是才是当前路径必须拓展点..但也有特判...那就是终点..因为终点只需到达不需要再出来了
...

Program:

/*  
ID: zzyzzy12   
LANG: C++   
TASK: betsy
*/      
#include<iostream>      
#include<istream>  
#include<stdio.h>     
#include<string.h>      
#include<math.h>      
#include<stack>
#include<map>
#include<algorithm>      
#include<queue>   
#define oo 2000000005  
#define ll long long 
#define pi (atan(2)+atan(0.5))*2 
using namespace std;  
int n,ans,i,j,data[9][9],tp; 
bool used[9][9];
void DFS(int y,int x,int p)
{
      if (used[y][x]) return;
      if (x==1 && y==n)
      {
            if (p==n*n) ans++; 
            return;
      } 
      if (p==n*n) return;  
      if (!used[y-1][x] && !used[y+1][x] && used[y][x-1] && used[y][x+1]) return;
      if (used[y-1][x] && used[y+1][x] && !used[y][x-1] && !used[y][x+1]) return;
      used[y][x]=true;  
      data[y-1][x]--; data[y+1][x]--;
      data[y][x-1]--; data[y][x+1]--;
      tp=0;
      if (!used[y-1][x] && data[y-1][x]==1 && (y-1!=n || x!=1)) tp=1;
      if (!used[y+1][x] && data[y+1][x]==1 && (y+1!=n || x!=1)) 
         if (tp!=0) tp=5; else tp=2;
      if (!used[y][x-1] && data[y][x-1]==1 && (y!=n || x-1!=1)) 
         if (tp!=0) tp=5; else tp=3;
      if (!used[y][x+1] && data[y][x+1]==1 && (y!=n || x+1!=1))
         if (tp!=0) tp=5; else tp=4; 
      if (tp==0)
      {
            DFS(y-1,x,p+1);
            DFS(y+1,x,p+1);
            DFS(y,x-1,p+1);
            DFS(y,x+1,p+1);    
      }else
      if (tp==1) DFS(y-1,x,p+1); else
      if (tp==2) DFS(y+1,x,p+1); else
      if (tp==3) DFS(y,x-1,p+1); else
      if (tp==4) DFS(y,x+1,p+1);
      data[y-1][x]++; data[y+1][x]++;
      data[y][x-1]++; data[y][x+1]++;
      used[y][x]=false;
      return; 
}
int main()  
{  
      freopen("betsy.in","r",stdin);   
      freopen("betsy.out","w",stdout); 
      scanf("%d",&n); 
      ans=0;
      for (i=0;i<=n+1;i++) used[0][i]=used[i][0]=used[n+1][i]=used[i][n+1]=true;  
      memset(data,0,sizeof(data));
      for (i=1;i<=n;i++)
         for (j=1;j<=n;j++)
         {
                if (!used[i-1][j]) data[i][j]++;
                if (!used[i+1][j]) data[i][j]++;
                if (!used[i][j-1]) data[i][j]++;
                if (!used[i][j+1]) data[i][j]++;    
         }
      DFS(1,1,1);
      printf("%d\n",ans); 
      return 0;     
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: