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;
}