`
lgh1992314
  • 浏览: 315650 次
文章分类
社区版块
存档分类
最新评论

HDOJ1175连连看

 
阅读更多

连连看

Time Limit: 20000/10000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10796Accepted Submission(s): 2869


Problem Description
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。

Input
输入数据有多组。每组数据的第一行有两个正整数n,m(0<n<=1000,0<m<1000),分别表示棋盘的行数与列数。在接下来的n行中,每行有m个非负整数描述棋盘的方格分布。0表示这个位置没有棋子,正整数表示棋子的类型。接下来的一行是一个正整数q(0<q<50),表示下面有q次询问。在接下来的q行里,每行有四个正整数x1,y1,x2,y2,表示询问第x1行y1列的棋子与第x2行y2列的棋子能不能消去。n=0,m=0时,输入结束。
注意:询问之间无先后关系,都是针对当前状态的!

Output
每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。

Sample Input
3 4 1 2 3 4 0 0 0 0 4 3 2 1 4 1 1 3 4 1 1 2 4 1 1 3 3 2 1 2 4 3 4 0 1 4 3 0 2 4 1 0 0 0 0 2 1 1 2 4 1 3 2 3 0 0

Sample Output
YES NO NO NO NO YES
开一个数组记录一下转向次数即可,杭电的数据弱爆了。
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
const int MAXN = 1001;
const int MAXINT = 999;
bool flag;
int n,m,sx,sy,ex,ey;
int Hash[MAXN][MAXN],map[MAXN][MAXN];
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
struct node{
	int x;
	int y;
	int turn;
	int d;
}start;

queue<node> Q;

void bfs()
{
	node now,t;
	while(!Q.empty())
	{
		now=Q.front();
		Q.pop();
		if(now.x == ex && now.y == ey && now.turn <= 2)
		{
			flag = true;
			return;
		}
		for(int i=0;i<4;i++)
		{
			t.x = now.x + dir[i][0];
			t.y = now.y + dir[i][1];
			if(now.d == i)
			{
				t.turn = now.turn;
				t.d = i;
			}
			else
			{
				t.turn = now.turn + 1;
				t.d = i;
			}
			if(t.x>=1 && t.x<=n && t.y>=1 &&t.y<=m && (map[t.x][t.y]==0||t.x==ex&&t.y==ey) && Hash[t.x][t.y]>=t.turn)
			{
				Hash[t.x][t.y] = t.turn;
				Q.push(t);
			}
		}
	}
}
int main()
{
	freopen("in.txt","r",stdin);
	int i,j,t;
	while(scanf("%d %d",&n,&m))
	{
		if(n==0 && m==0) break;
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++) 
				scanf("%d",&map[i][j]);
		scanf("%d",&t);
		while(t--)
		{
			scanf("%d %d %d %d",&sx,&sy,&ex,&ey);
			if((map[sx][sy]!=map[ex][ey]) || map[sx][sy]==0 || map[ex][ey]==0 || (sx==ex&&sy==ey))
			{
				puts("NO");
				continue;
			}
			for(i=1;i<=n;i++)
				for(j=1;j<=m;j++) 
					Hash[i][j]=MAXINT;
			while(!Q.empty()) 
				Q.pop();
			for(i=0;i<4;i++)
			{
				start.x = sx;
				start.y = sy;
				start.turn = 0;
				start.d = i;
				Q.push(start);
			}
			flag = false;
			Hash[sx][sy] = 0;
			bfs();
			puts(flag ? "YES":"NO");
		}
	}
	return 0;
}




#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
const int MAXN = 1001;
const int MAXINT = 99999;
int maps[MAXN][MAXN];
int mark[MAXN][MAXN];
int n, m, sx, sy, ex, ey, t;
int mov[ 4 ][ 2 ] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

struct Node {
	int x;
	int y;
	int turn;
	int dir;
}Next,now;

queue<Node> Q;

void BFS() {
	now.x = sx;   
	now.y = sy;
	mark[ sx ][ sy ] = 0;
	now.dir = -1; 
	now.turn = 0;
	Q.push(now);
	while(!Q.empty()) 
	{
		now = Q.front();
		Q.pop();
		if(now.x == ex && now.y == ey) 
		{	
			puts("YES");
			return ;
		}
		//0下, 1上, 2左, 3右
		for(int i = 0; i < 4; ++ i) 
		{
			Next.x = now.x + mov[ i ][ 0 ];
			Next.y = now.y + mov[ i ][ 1 ];
			Next.turn = now.turn;
			Next.dir = now.dir;
			if(now.dir == -1) 
			{
				Next.dir = i;
				Next.turn = 0;
			}
			else if(now.dir != i) 
			{

				Next.turn ++;
				Next.dir = i;
			}
			if(maps[ Next.x ][ Next.y ] && !(Next.x == ex && Next.y == ey) || Next.turn > 2) continue;
			if(Next.x>=1 && Next.x<=n && Next.y>=1 && Next.y<=m && mark[ Next.x ][ Next.y ] >= Next.turn) 
			{
				mark[ Next.x ][ Next.y ] = Next.turn;
				Q.push(Next);
			}
		}
	}
	puts("NO");
}

int main() 
{
	freopen("in.txt","r",stdin);
	while(~scanf("%d %d", &n, &m)) 
	{
		if(n == 0 && m == 0) break;
		for(int i = 1; i <= n; ++ i) 
		{
			for(int j = 1; j <= m; ++ j) 
			{
				scanf("%d", &maps[ i ][ j ]);
			}
		}
		scanf("%d", &t);
		while(t --) 
		{
			scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
			if(sx == ex && sy == ey) 
			{

				puts("NO");
				continue;
			}
			if(maps[ sx ][ sy ] != maps[ ex ][ ey ] || maps[ sx ][ sy ] == 0 || maps[ ex ][ ey ] == 0) 
			{


				puts("NO");
				continue;
			}

			for(int i = 1; i <= n; ++ i) 
			{
				for(int j = 1; j <= m; ++ j) 
				{
					mark[ i ][ j ] = MAXINT;
				}
			}
			while(!Q.empty())
				Q.pop();
			BFS();
		}
	}
	return 0;
}

DFS版本:
#include <iostream>   
#include <cstdio>   
#include <cstring>   
using namespace std;   

int n, m, t, k, z;   
int sx, sy, ex, ey;   
int a[1005][1005];   
bool map[1005][1005], flag;   

void init()     //初始化函数   
{   
	flag = false;   
	memset(map, false, sizeof(map));   
}   

void dfs(int x, int y, int z, int k)    //坐标(x,y)   
{   
	if(flag) return;   
	if(x<=0 || y<=0 || x>n || y>m) return;  //若超界,返回   
	if(k>=3) return;        //若转弯数已经超过3次,返回   
	if(x == ex && y == ey)   
	{   
		flag = true;   
		return;   
	}   
	if(k == 2)  //超强剪枝:若已经转两次弯,则目标坐标必须要在前进方向的前面,否则直接返回   
	{   
		if( !(z==1 && x>ex && y==ey  ||  z==2 && x<ex && y==ey   
			||  z==3 && y>ey && x==ex  ||  z==4 && y<ey && x==ex) )   
			return;   
	}   
	if(a[x][y] != 0) return;    //如果该点不是0,则不能走,返回   
	if(map[x][y]) return;       //如果该点已经走过,返回   
	map[x][y] = true;       //标记该点为走过   
	if(z == 1)  //上   
	{   
		dfs(x-1, y, 1, k);   
		dfs(x+1, y, 2, k+1);   
		dfs(x, y-1, 3, k+1);   
		dfs(x, y+1, 4, k+1);   
	}   
	else if(z == 2) //下   
	{   
		dfs(x-1, y, 1, k+1);   
		dfs(x+1, y, 2, k);   
		dfs(x, y-1, 3, k+1);   
		dfs(x, y+1, 4, k+1);   
	}   
	else if(z == 3) //左   
	{   
		dfs(x-1, y, 1, k+1);   
		dfs(x+1, y, 2, k+1);   
		dfs(x, y-1, 3, k);   
		dfs(x, y+1, 4, k+1);   
	}   
	else if(z == 4) //右   
	{   
		dfs(x-1, y, 1, k+1);   
		dfs(x+1, y, 2, k+1);   
		dfs(x, y-1, 3, k+1);   
		dfs(x, y+1, 4, k);   
	}   
	map[x][y] = false;  //若深搜不成功,标记该点为未走过   
}   

int main()   
{
	freopen("in.txt","r",stdin);
	int i, j;   
	while(scanf("%d %d", &n, &m))   
	{   
		if(n==0 && m==0) break;   
		for(i = 1; i <= n; i++)   
			for(j = 1 ; j <= m; j++)   
				scanf("%d", &a[i][j]);   
		scanf("%d", &t);   
		for(i = 0; i < t; i++)   
		{   
			init();   
			scanf("%d %d %d %d", &sx, &sy, &ex, &ey);   
			if(a[sx][sy]!=a[ex][ey] || a[sx][sy]==0 || a[ex][ey]==0 || sx==ex && sy==ey)
				puts("NO");
			else
			{
				dfs(sx-1, sy, 1, 0);   
				dfs(sx+1, sy, 2, 0);   
				dfs(sx, sy-1, 3, 0);   
				dfs(sx, sy+1, 4, 0);   
				if(flag) puts("YES");  
				else puts("NO"); 
			}
		}   
	}   

	return 0;   
}  



分享到:
评论

相关推荐

    C#可视化连连看实现 广度优先,动态规划,回溯

    在本项目中,"C#可视化连连看实现 广度优先,动态规划,回溯" 是一个使用C#编程语言实现的连连看游戏,它融合了三种算法:广度优先搜索(BFS)、动态规划(DP)和回溯法。这些算法在解决复杂问题时非常有效,尤其是...

    HDOJ题目分类 HDOJ题目分类

    【标题】:“HDOJ题目分类 HDOJ题目分类” HDOJ,全称为Happy DingO Online Judge,是一个在线编程竞赛平台,它为参赛者提供了大量编程题目进行练习和比赛,旨在提升编程技能和算法理解。HDOJ的题目分类是帮助用户...

    hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000

    【标题】"hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000" 涉及的知识点主要围绕着“杭电在线判题系统(HDOJ)”以及其中的题目1082和10系列题目。HDOJ是杭州电子科技大学主办的一个在线编程竞赛平台,...

    HDOJ部分简单题(JAVA)

    HDOJ1000.java HDOJ1001.java HDOJ1089.java HDOJ1090.java HDOJ1091.java HDOJ1092.java HDOJ1093.java HDOJ1094.java HDOJ1095.java HDOJ1108.java HDOJ1406.java HDOJ2001.java HDOJ2002.java HDOJ2003.java HDOJ...

    HDOJ1002

    ACM ICPC HDOJ1002

    hdoj1001标程

    hdoj1001标程

    HDOJ1001

    ACM ICPC HDOJ1001

    HDOJ 80题 Java

    【标题】"HDOJ 80题 Java"是一份专为Java程序员设计的在线编程挑战集合,源自杭州电子科技大学(HDOJ)的在线评测系统。这些题目旨在帮助Java开发者提升算法理解与编程能力,同时也为那些习惯于C++但希望在Java环境...

    hdoj1004 解题代码 答案

    hdoj1004,解题代码,答案代码,欢迎下载

    HDOJ1003

    ACM ICPC HDOJ1003

    HDOJ离线版

    《HDOJ离线版:探索编程竞赛的智慧宝库》 HDOJ,全称为“杭州电子科技大学在线评测系统”(Hangzhou Dianzi University Online Judge),是中国早期的编程竞赛平台之一,深受广大编程爱好者和在校学生的喜爱。HDOJ...

    HDOJ 1008

    ACM ICPC HDOJ1008

    hdoj--acm题目,有注释

    "hdoj--acm题目,有注释" 本资源提供了多个 ACM 题目的解决方案,代码都带有注释,非常适合初学者学习。下面是对每个题目的知识点总结: 2000:本题目要求输入三个字符,输出按照从小到大排序的结果。本代码使用了...

    hdoj2066最短路

    根据给定的文件信息,我们可以总结出以下关于“hdoj2066最短路径”的相关知识点: ## hdoj2066最短路径概述 ### 标题解析:“hdoj2066最短路” - **hdoj**:High Density Online Judge(高密度在线评测系统),是...

    HDOJ1000

    ACM ICPC HDOJ1000

    HDOJ.rar_HD_HDOJ

    【标题】"HDOJ.rar_HD_HDOJ" 是一个与HDU(杭州电子科技大学)在线判题系统HDOJ相关的压缩包文件,其中包含了大量编程题目的源代码。 【描述】提到,这个压缩包包含了几百道HDOJ题目的源代码,这意味着它是一个宝贵...

    OJ.tar.gz_HDOJ _OJ源码_oj

    【OJ.tar.gz_HDOJ _OJ源码_oj】是一个包含编程竞赛平台HDOJ(Happy Ding Octopus Judge)部分源代码的压缩文件。这个压缩包的主要目的是供学习和研究使用,尤其是针对50至60题目的解题算法和系统实现。通过分析这些...

    HDOJ DP题目总结

    一些HDOJ上的DP题目的小总结,但愿能帮到那些想专攻DP的人吧

    hdoj 2013 多校训练4标程+解题报告

    【标题解析】:“hdoj 2013 多校训练4标程+解题报告”这个标题表明,这是一个关于2013年Happy Dream Online Judge(简称hdoj)组织的多校联合编程训练的资料。"4标程"意味着包含了四道题目(或者可能是四个阶段)的...

    hdoj1002——大整数相加

    ### hdoj1002——大整数相加 #### 题目背景与目的 本题目来源于杭州电子科技大学的在线评测系统(HDOJ),编号为1002的大整数相加问题。该题目主要考察的是编程者对于大整数处理的基本技巧以及对数组、循环等基础...

Global site tag (gtag.js) - Google Analytics