HDU 1175 连连看

连连看

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)



Problem Description
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。
 

 

Input
输入数据有多组。每组数据的第一行有两个正整数n,m(0<n<=1000,0<m<1000),分别表示棋盘的行数与列数。在接下来的n行中,每行有m个非负整数描述棋盘的方格分布。0表示这个位置没有棋子,正整数表示棋子的类型。接下来的一行是一个正整数q(0<q<50),表示下面有q次询问。在接下来的q行里,每行有四个正整数x1,y1,x2,y2,表示询问第x1行y1列的棋子与第x2行y2列的棋子能不能消去。n=0,m=0时,输入结束。
注意:询问之间无先后关系,都是针对当前状态的!
 

 

Output
每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。
 

 

Sample Input
3 4
1 2 3 4
0 0 0 0
4 3 2 1
4
1 1 3 4
1 1 2 4
1 1 3 3
2 1 2 4
3 4
0 1 4 3
0 2 4 1
0 0 0 0
2
1 1 2 4
1 3 2 3
0 0

Sample Output
YES
NO
NO
NO
NO
YES

  
这个题之所以我现在还把它放在这里:
    (1) 和一般的dfs有点小区别
    (2) 当前的访问点(x,y)不能随意标记已访问 。
    (2) 对于每个点应该抽象成为12种情况
                    (A,B )
                A :  方向(4种)
                B : 转折次数 (3种)
     很多人说这个题数据有毛病,其实是没有搞清楚实质。
#include <iostream>
#include <string>
#include <string.h>
#include <map>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <math.h>
#include <set>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#pragma comment(linker, "/STACK:16777216")
using namespace std ;
typedef long long LL ;
int  chess[1008][1008] ;
bool visited[1008][1008][4][3] ;
class LLK{
  private :
     int  N ;
     int  M ;
     static int d[4][2] ;
  public  :
     LLK() ;
     LLK(int ,int) ;
     void read() ;
     int cango(int,int) ;
     int dfs(int ,int ,int ,int ,int ,int) ;
     void gao() ;
};

LLK::LLK(){

}

LLK::LLK(int n ,int m):N(n),M(m){

}

int LLK::d[4][2] = {{-1,0},{0,-1},{1,0},{0,1}} ;

void LLK::read(){
     for(int i = 1 ;i <= N ;i++)
        for(int j = 1 ;j <= M ;j++)
          scanf("%d",&chess[i][j]) ;
}

int LLK::cango(int x ,int y){
     return 1<=x&&x<=N&&1<=y&&y<=M ;
}

int LLK::dfs(int x ,int y,int ex,int ey ,int direc ,int turn){
    if(direc != -1)
       visited[x][y][direc][turn] = 1 ;
    if(x == ex && y== ey)
       return 1 ;
    for(int i = 0 ; i < 4 ;i++){
        int nx = x + d[i][0] ;
        int ny = y + d[i][1] ;
        int nd ,nt;
        if(!cango(nx,ny))
            continue ;
        if((chess[nx][ny] != 0) && !(nx == ex && ny == ey))
            continue ;
        if(direc == -1)
            nt = 0 ;
        else if(direc == i)
            nt = turn ;
        else
            nt = turn + 1 ;
        nd = i ;
        if(visited[nx][ny][nd][nt])
            continue ;
        if(turn > 2)
            continue ;
        if(dfs(nx,ny,ex,ey,nd,nt))
            return 1 ;
    }
    return 0 ;
}

void LLK::gao(){
     int q ,sx ,sy,ex,ey ;
     scanf("%d",&q) ;
     while(q--){
         scanf("%d%d%d%d",&sx,&sy,&ex,&ey) ;
         if(chess[sx][sy] != chess[ex][ey])
            puts("NO")  ;
         else if(chess[sx][sy] == 0 || chess[ex][ey] == 0)
            puts("NO")  ;
         else{
            memset(visited,0,sizeof(visited)) ;
            if(dfs(sx,sy,ex,ey,-1,0))
               puts("YES") ;
            else
               puts("NO") ;
          }
     }
}

int main(){
    int n , m  ;
    while(scanf("%d%d",&n,&m)){
        if(n == 0 && m == 0)
           break ;
        LLK llk(n,m) ;
        llk.read() ;
        llk.gao() ;
    }
    return 0 ;
}

 

你可能感兴趣的:(HDU 1175 连连看)