HDU 1175 连连看

http://acm.hdu.edu.cn/showproblem.php?pid=1175

一个连连看的题目,DFS+剪枝。

代码:

/*
HDU 1175 连连看
Tips : 搜索+剪枝
*/
#include<stdio.h>
#include<string.h>
int n,m,q,tr,tc,sr,sc;
int map[1005][1005] ;
int vis[1005][1005] ,visn;
int dr[4] = {-1,1,0,0} ;
int dc[4] = {0,0,-1,1} ;
bool flag ;
void dfs(int r, int c,int t, int dir){
    if(flag)    return ;        //已经找到了 ;
    if(t>=3)  return ;          //折线次数超过2次
    if(r==tr && c==tc)  {       //找到目标节点
        flag = true ;   return ;
    }
    if(r<1 || r>n || c<1 || c>m || map[r][c]!=0 || vis[r][c]==visn)    return ;         //坐标越界
    if(t==2){                   //强剪枝,折线的次数已经到达了两次,以后的操作都是在dir的方向,没有此剪枝为3600+ms,有46ms
        if(!(dir==0&&tc==c&&tr<r || dir==1&&tc==c&&tr>r || dir==2&&tr==r&&tc<c || dir==3&&tr==r&&tc>c)){
            return ;
        }
    }
    vis[r][c] = visn ;
    for(int i=0;i<4;i++){           //四个搜索方向
        int rr = r + dr[i] ;
        int cc = c + dc[i] ;
        if( i==dir )
            dfs(rr,cc,t,i);
        else
            dfs(rr,cc,t+1,i);
    }
    vis[r][c] = visn - 1 ;
}
int main(){
	memset(vis,0,sizeof(vis));	visn = 0 ;
	while(scanf("%d %d",&n,&m) && (n||m)){
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				scanf("%d",&map[i][j]);
			}
		}
		scanf("%d",&q);
		for(int i=1;i<=q;i++){
			scanf("%d %d %d %d",&sr,&sc,&tr,&tc);
			if(sr==tr && sc==tc && map[sr][sc]!=0){     //两个点重合
				printf("NO\n");	continue ;
			}
			flag = false ;
            if(map[sr][sc]==map[tr][tc] && map[sr][sc]!=0){     //两个相同的点,且不为零
				visn++ ;  vis[sr][sc] = visn ;
				for(int i=0;i<4;i++){
                    dfs(sr+dr[i],sc+dc[i],0,i);
                }
				if(flag)    printf("YES\n");
				else    printf("NO\n");
			}
			else	printf("NO\n");
		}
	}
	return 0;
}



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