HDU 1175 练练看
来源:互联网 发布:全球人工智能产业规模 编辑:程序博客网 时间:2024/04/30 10:53
连连看
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 28609 Accepted Submission(s): 7133
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 41 2 3 40 0 0 04 3 2 141 1 3 41 1 2 41 1 3 32 1 2 43 40 1 4 30 2 4 10 0 0 021 1 2 41 3 2 30 0
Sample Output
YESNONONONOYES
【分析】
这题说多了全是泪啊,怎么做都不对,不对就扔一边了,就这样做做扔扔两个星期终于弄出来了, 这个题刚开始想简单了,通过学长一点点的说,才知道这题考虑的内容很多,需要很多细节考虑,我是用 队列做的,用优先队列做就不用考虑这么多条件,用栈做也可以就是有点耗时,除非是标记入栈元素,标记 也要规律,想标记某一点不是它入栈就标记,而是等这点往4个方向都走完时,才能标记。总体来说还是 用优先队列好,但是不太会,所以用队列写的。用队列需要考虑遍历到某点时拐的次数,不像是之前那样 遍历过就标记,现在还得储存到该点的拐点数,如果大于之前遍历过时的拐点数就不入队。其实我做到这 用不知道哪错了,停了一星期用接着做的,之前我是只算的小于时入队,但是等于时也要入队,进行遍 历,因为遍历到这点的路径有很多,方向都不一样,虽然拐点数可能相等,但是方向不一样,会影响下步 的拐点次数,所以相等也要入队。
【扩展】
还有hdu上后台数据有点少,会出现错误的也能对,我做完才发现的,只要你改变方向数组的顺序就行 了,我之前用的是下上右左提交不对,改为右左下上就对了,太神奇了!
【代码】
#include<stdio.h>#include<string.h>#include<queue>#include<iostream>#define INF 0x3f3f3f3fusing namespace std;int e[1010][1010],book[1010][1010];int n,m,x2,y2;struct node{ int x,y,z,f;};int fang[4][2]={{1,0},{-1,0},{0,1},{0,-1}};void dfs(int x,int y){ queue<node>q; struct node a,b; a.x=x; a.y=y; a.f=5; a.z=0; q.push(a); int flag=0; while(!q.empty()) { if(flag==1) break; b=q.front(); q.pop(); //printf("#####%d %d\n",b.x,b.y); for(int k=0;k<4;k++) { a.x=b.x+fang[k][0]; // 下一步x的坐标 a.y=b.y+fang[k][1]; // 下一步y的坐标 a.z=b.z; // 之前拐的次数 a.f=k; // 记录方向,用来判断拐没怪 if(b.f!=k) a.z=a.z+1; if(a.x>0&&a.x<=n&&a.y>0&&a.y<=m&&a.z<=3) { //printf("%d %d\n",a.x,a.y); if(a.x==x2&&a.y==y2) // 先讨论是不是到达终点,因为终点对应值不为0,不往下执行 { flag=1; break; } if(!e[a.x][a.y]) { /* 虽然是最小拐数,但是下步拐不拐还不知道,所以必须小于等于,不能小于。 如果是小于就这个地方只执行一次,有可能第一次执行是不能到达目标,第二次从这里相等的拐次能到达目标, 这个位置下面有4个方向,虽然到这的拐数相同,但是方向不同,在这点走同一个方向,对相同拐数的方法可能 是同向可能不同向,所以分开讨论 */ if(a.z<=book[a.x][a.y]) // book[][]数组不能单纯的记录走没走过,也要记录走到这拐的次数,如果第一次走到这,拐次特别大就认为这个点不能到达, // 第二次拐次特别小,能到达也无法往下执行 { book[a.x][a.y]=a.z; q.push(a); } //printf("%d %d\n",a.x,a.y); } } } } if(flag) printf("YES\n"); else printf("NO\n");}int main(){ while(scanf("%d %d",&n,&m)&&(n+m)) { int i,j; memset(e,0,sizeof(e)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&e[i][j]); int t; scanf("%d",&t); while(t--) { int x1,y1; for(i=1;i<=n;i++) for(j=1;j<=m;j++) book[i][j]=INF; // 把book置无限大,用来保存到某点时之前拐的次数,和来过这点 scanf("%d %d %d %d",&x1,&y1,&x2,&y2); if(e[x1][y1]==e[x2][y2]&&e[x1][y1]!=0&&e[x2][y2]!=0&&(x1!=x2||y1!=y2)) // 如果最基本的条件不满足,就不执行,否则浪费时间,还会出错 dfs(x1,y1); else printf("NO\n"); } } return 0;}分析或代码有错,请记得留言
0 0
- HDU 1175 练练看
- wpf 练练看UI 用代码布局
- 练练
- 练练
- 练练
- 练练
- hdu 1175 连连看
- hdu 1175 连连看
- hdu 1175 连连看
- HDU 1175 连连看
- HDU 1175 ( 连连看 )
- hdu 连连看 1175
- hdu 1175 连连看
- hdu 1175连连看
- HDU 1175 连连看
- hdu 1175 连连看
- HDU 1175 连连看
- HDU 1175 连连看
- 图文详解如何快捷搭建LNMP服务环境
- Installation error: INSTALL_FAILED_CPU_ABI_INCOMPATIBLE的解决方法
- LintCode:图中两个点之间的路线
- nyoj 1023 还是回文 (区间dp加贪心)
- PHP数组函数基础知识
- HDU 1175 练练看
- 如何对ZBrush中面部进行快速布线
- Android学习--《Fragment》
- 【客户端】windows c++ 检查图像文件是否有效(Check if file is valid image)
- 互斥锁、条件变量:生产者消费者问题
- AndroidStudio添加导入一个AndroidStudio工程作为一个Library
- java进阶书籍推荐(不包括基础)
- gcc & makefile
- iOS版本更新提示