HDU 1175 连连看 (搜索,dfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175

类似于迷宫问题,主要就在转折的处理上,在这里可以有一个强剪枝,具体见代码。

参考博客:http://www.cnblogs.com/qiu520/p/3250167.html    感谢!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int map[1010][1010];
int tmap[1010][1010];
int n, m, q;
int x1, y1, x2, y2;
int flag;
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0}; // 右下左上1234 
void dfs(int x, int y, int chg, int d) {
	if(flag) return ;
	int i;
	if(chg >= 3) return ;
	if(chg == 2) {
		//强剪枝 ,不然超时 
		if(	d == 1 && x != x2 || 
			d == 2 && y != y2 || 
			d == 3 && x != x2 || 
			d == 4 && y != y2) {
			return ;
		} 
	}
	if(x == x2 && y == y2) {
		flag = 1;
		printf("YES\n");
		return ;
	}
	for(i = 0; i < 4; i++) {
		int tx = x + dir[i][0];
		int ty = y + dir[i][1];
		if(tx < 1 || tx > n || ty < 1 || ty > m || tmap[tx][ty] != 0) {
			continue;
		}
		tmap[tx][ty] = -1;
		if(d == 0) {
			dfs(tx, ty, chg, i + 1);
		}
		else {
			if(d != i + 1) {
				dfs(tx, ty, chg + 1, i + 1);
			}
			else {
				dfs(tx, ty, chg, i + 1);
			}
		}
		tmap[tx][ty] = 0;  //不要忘记回溯,因为已经走过的地方下次还有可能走 
	}
}
int main() {
	while(~scanf("%d %d", &n, &m) && m + n) {
		int i, j;
		for(i = 1; i <= n; i++) {
			for(j = 1; j <= m; j++) {
				scanf("%d", &map[i][j]);
			}
		}
		scanf("%d", &q);
		while(q--) {
			scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
			memcpy(tmap, map, sizeof(map));
			if(tmap[x1][y1] == 0 || tmap[x1][y1] != tmap[x2][y2]) {  //首先看是否有数是否是两个相同的数 
				printf("NO\n");
				continue;
			}
			else {
				tmap[x2][y2] = 0;  //以便最后可以走这里 
			}
			flag = 0;
			tmap[x1][y1] = -1;
			dfs(x1, y1, 0, 0);
			if(flag == 0) printf("NO\n");
		}
	}
	return 0;
}


你可能感兴趣的:(HDU 1175 连连看 (搜索,dfs))