hdu 1175 [连连看] dfs搜索

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


题目大意:= = 因为是中文题,就不多说了。  题目对两块棋子能否消除的限制为 两者之间的连线不能转向2次以上,并且不能穿过其他棋子.


个人想法:dfs.如果能满足题目的条件从一块搜索到另一块,那么就输出YES,否则NO。


= =。 但这边不知道为何,如果没有在转向两次以后进行剪枝(接下去就只朝一个方向走)的话,就是超时.

结合网上的题解,进行了剪枝.

剪了枝之后时间一下子就从超时降到了 3700ms.

- -. 只能在这边感叹搜索算法中剪枝的重要性.


以下是ac代码

#include <stdio.h>
#include <string.h>

int map[1010][1010];
char vis[1010][1010];
int m,n;

int tx[] = {0,0,0,-1,1};
int ty[] = {0,1,-1,0,0};

/* 0:原地,1:上,2:下,3:左,4:右 */

int dfs(int s_x,int s_y,int e_x,int e_y,int dir,int change){
	
	if(change==4)
		return 0;

	if(s_x == e_x && s_y == e_y){
		return 1;
	}
	
	if(vis[s_x][s_y])
		return 0;

	int i;
	int ex;
	int ey;
	int ans = 0;

	vis[s_x][s_y] = 1;
	if(change==3){
		ex = s_x + tx[dir];
		ey = s_y + ty[dir];
		if(ex>=1 && ex<=m && ey>=1 && ey<=n && (map[ex][ey]==0 || ex==e_x && ey==e_y)){
				if(dfs(ex,ey,e_x,e_y,dir,change))
					return 1;
			}
	}/*摘自网上的对于 换了2次后的 优化*/
	else{
		for(i=1;i<=4;i++){
			ex = s_x + tx[i];
			ey = s_y + ty[i];
			if(ex>=1 && ex<=m && ey>=1 && ey<=n && (map[ex][ey]==0 || ex==e_x && ey==e_y)){
				if(dir!=i){
					if(dfs(ex,ey,e_x,e_y,i,change+1))
						return 1;
				}
				else{
					if(dfs(ex,ey,e_x,e_y,i,change))
						return 1;
				}
			}
		}
	}
	vis[s_x][s_y] = 0;/*为了回溯*/
	return 0;
}



int main(int argc, char const *argv[])
{
	while(scanf("%d %d",&m,&n)!=EOF&&(m||n)){
		int i,j;
		for(i=1;i<=m;i++)
			for(j=1;j<=n;j++)
				scanf("%d",&map[i][j]);

		
		int T;
		scanf("%d",&T);
		int x1,y1,x2,y2;
		while(T--){
			scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
			memset(vis,0,sizeof(vis));
			if(map[x1][y1]!=map[x2][y2]||(!(map[x1][y1]||map[x2][y2])))
				printf("NO\n");
			else{
				if(dfs(x1,y1,x2,y2,0,0) == 1)
					printf("YES\n");
				else
					printf("NO\n");
			}

		}
	}
	return 0;
}


第一篇题解

也是前几道搜索的尝试,第一次体会到剪枝的牛X.

如果有什么问题,欢迎指出,

如果有什么错误,也请看官轻拍.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值