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