HDU1175 连连看【DFS+剪枝】

连连看

题意: 给定一个n*m的连连看的图,有q次操作,问点击(sx,sy)与(ex,ey)能否使方格消失(!!但是,就算可以消失,也不能改变原图,这q次操作相互之间没有联系)。消失的条件详见题目。

题解: 一开始还以为是判断给定的连连看图能否全部消失,但是只是针对两个方格的询问,并且前后没有联系的话,那只要通过DFS就能做,无非多一个记录路线方向以及拐弯次数。针对这个拐弯次数,可以有一个剪枝,有无这个剪枝,是109MS和6770MS的差距,不过题目给的时间足够长,所以没有剪枝也能过。

#include<bits/stdc++.h>
using namespace std;

const int N = 1e3 + 10;
int flag;
int n, m, q;
int sx, sy;
int ex, ey;
int G[N][N];
int vis[N][N];
int dir[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; 

void dfs(int x, int y, int di, int cnt) {	//坐标、路线防线、拐弯次数
	if(cnt > 2 || flag)	return;				//超过限定的拐弯次数或者已经判断到可以消失了,退出
	if(cnt == 2 && (x - ex) != 0 && (y - ey) != 0)	return ;	//剪枝:拐弯次数已达上限
	//直接判断此时的坐标与目标坐标是否在同一直线,不在即可退出
	if(x == ex && y == ey) {
		flag = 1;
		return ;
	}
	for(int i = 0; i < 4; i++) {
		int nx = x + dir[i][0];
		int ny = y + dir[i][1];
		if(nx < 1 || nx > n || ny < 1 || ny > m || vis[nx][ny])	continue;
		if(G[nx][ny] == 0 || nx == ex && ny == ey) {
			vis[nx][ny] = 1;
			if(di == -1 || di == i)	dfs(nx, ny, i, cnt);
			else					dfs(nx, ny, i, cnt + 1);
			vis[nx][ny] = 0;	//回溯:很重要的一环,判断完某条路线之后记得恢复vis标记
		}
	}
	return ;
}

int main() {
	while(~scanf("%d%d", &n, &m) && (n + m)) {
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= m; j++)
				scanf("%d", G[i] + j);
		scanf("%d", &q);
		while(q--) {
			flag = 0;
			memset(vis, 0, sizeof vis);
			scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
			if(G[sx][sy] == G[ex][ey] && G[sx][sy])	dfs(sx, sy, -1, 0);
			if(flag)	printf("YES\n");
			else		printf("NO\n");
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值