Program2_1009

 我现在做的是第二专题编号为1009的试题,具体内容如下所示:

连连看

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

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时,输入结束。<br>注意:询问之间无先后关系,都是针对当前状态的!<br>
 

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

Sample Input
  
  
3 4<br>1 2 3 4<br>0 0 0 0<br>4 3 2 1<br>4<br>1 1 3 4<br>1 1 2 4<br>1 1 3 3<br>2 1 2 4<br>3 4<br>0 1 4 3<br>0 2 4 1<br>0 0 0 0<br>2<br>1 1 2 4<br>1 3 2 3<br>0 0<br>
 

Sample Output
  
  
YES<br>NO<br>NO<br>NO<br>NO<br>YES<br>

简单题意:

 判断是否能完成连连看,规则与我们玩的规则差不多,但不能从外围连线,这与传统的玩法有区别


解题思路:

这道题将BFS做一点小小的变形,即每次让一个方向的可能点全部入对列,这样能够使得拐弯次数限制到最小,标记的变量要设四个方向,每次走过的点要标记两个方向,向前和向后,显然不可能再次走到这一点以相同的方向或者反过来。其他就和一般的BFS差不多了


编写代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#define INF 0x7f7f7f7f
using namespace std;
 
int map[1005][1005], hash[4][1005][1005], dir[4][2]= { 1, 0, -1, 0, 0, 1, 0, -1 };
 
struct Node
{
    int x, y, type, ti, dir;
}info;
 
void gint( int &t )
{
    char c;
    while( c= getchar(), c< '0'|| c> '9' ) ;
    t= c- '0';
    while( c= getchar(), c>= '0'&& c<= '9' )
    {
        t= t* 10+ c- '0';
    }
}
 
bool BFS( int sx, int sy, int ex, int ey )
{
    queue< Node >q;
    memset( hash, 0, sizeof( hash ) );
    info.x= sx, info.y= sy, info.type= map[sx][sy], info.ti= 0, info.dir= -1;
    hash[0][sx][sy]= hash[1][sx][sy]= hash[2][sx][sy]= hash[3][sx][sy]= 1;
    q.push( info );
    while( !q.empty() )
    {
        Node pos= q.front();
        q.pop();
        if( pos.x== ex&& pos.y== ey )
        {
            return true;
        }
        for( int i= 0; i< 4; ++i )
        {
            int x= pos.x+ dir[i][0], y=pos.y+ dir[i][1], ti= pos.ti, d= pos.dir;
            while( ( map[x][y]== 0|| ( x== ex&& y== ey ) )&& !hash[i][x][y] )
            {
                int k= ( i== d|| d== -1 )? 0: 1;
                info.x= x, info.y= y, info.ti= ti+ k, info.dir= i;
                if( info.ti<= 2 )
                {
                    if( info.ti< 2|| ( info.ti== 2 && ( x== ex|| y== ey ) ) )
                    {
                        q.push( info );
                    }
                    hash[i][x][y]= 1;
                    if( i== 0|| i== 1 )
                    {
                        hash[!i][x][y]= 1;
                    }
                    else if( i== 2 )
                    {
                        hash[3][x][y]= 1;
                    }
                    else
                    {
                        hash[2][x][y]= 1;
                    }
                }
                x+= dir[i][0], y+= dir[i][1];
            }
        }
    }
    return false;
}
 
int main()
{
    int N, M;
    while( scanf( "%d %d", &N, &M ), N| M )
    {
        memset( map, 0x7f, sizeof( map ) );
        for( int i= 1; i<= N; ++i )
        {
            for( int j= 1; j<= M; ++j )
            {
                gint( map[i][j] );
            }
        }
        int q;
        scanf( "%d", &q );
        while( q-- )
        {
            int sx, sy, ex, ey;
            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;
            }
            printf( BFS( sx, sy, ex, ey )? "YES\n": "NO\n" );
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值