hdoj1175 連連看(dfs+剪枝)

處理連連看問題。ios

要求拐彎方向很少於兩次。剪枝很重要!!!spa

用dir記錄當前方向。Orz,竟然沒想到。3d

 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 }