hdoj1175 连连看(dfs+剪枝)
处理连连看问题。
要求拐弯方向不多于两次。剪枝很重要!!!
用dir记录当前方向。Orz,居然没想到。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #define maxn 1005 5 using namespace std; 6 const int dx[]={-1,1,0,0},dy[]={0,0,-1,1}; 7 int map[maxn][maxn],V[maxn][maxn]; 8 int n,m,flag,x1,x2,y1,y2; 9 void dfs(int x,int y,int num,int dir){ 10 if (flag || x<0 || x>=n || y<0 || y>=m || V[x][y]) return ; 11 if (num==2 && x!=x2 && y!=y2) return ;//当拐弯数为2,但与终点不在同一方向 12 if (num>2) return ; 13 if (num<=2 && x==x2 && y==y2){ 14 flag=1; 15 return ; 16 } 17 if (map[x][y]!=0){ 18 if (x==x1 && y==y1) ; 19 else return ; 20 }//当前不为零且不为起点,即路径上有棋子 21 V[x][y]=1; 22 for (int i=0;i<4;i++){ 23 int xx=x+dx[i],yy=y+dy[i]; 24 if (i==dir) dfs(xx,yy,num,i); 25 else dfs(xx,yy,num+1,i); 26 } 27 V[x][y]=0; 28 return ; 29 } 30 int main(){ 31 int t; 32 while (cin >> n >> m && n+m){ 33 memset(map,0,sizeof(map)); 34 for (int i=0;i<n;i++){ 35 for (int j=0;j<m;j++){ 36 cin >> map[i][j]; 37 } 38 } 39 cin >> t; 40 while (t--){ 41 cin >> x1 >> y1 >> x2 >> y2; 42 x1--,y1--,x2--,y2--; 43 if (x1==x2 && y1==y2){ 44 cout << "NO\n"; 45 continue; 46 }//起点与终点相同不能消去 47 if (map[x1][y1]!=map[x2][y2] || !map[x1][y1] || !map[x2][y2]){ 48 cout << "NO\n"; 49 continue; 50 }//起点与终点不同,或起点或终点位置没有棋子 51 if (x1<0 || x1>=n || y1<0 || y1>=m || x2<0 || x2>=n || y2<0 || y2>=m){ 52 cout << "NO\n"; 53 continue; 54 }//所给坐标超出当前范围 55 flag=0; 56 memset(V,0,sizeof(V)); 57 for (int i=0;i<n;i++){ 58 dfs(x1+dx[i],y1+dy[i],0,i); //从一个点的四个方向开始 ,拐弯数 ,当前方向 59 } 60 if (flag) cout << "YES\n"; 61 else cout << "NO\n"; 62 } 63 } 64 return 0; 65 }