HDU_1175 连连看(BFS)

题目请点我

题解:

题目的意思就是针对当前的残局,输入多组检测看是否能消去。对于每组消去的规则是连线不能超过两折。这道题可以用BFS,也可以用DFS。但是觉得BFS要简单一些,如果用DFS的话注意减枝。BFS的话最先找到的是最短的路径,但是可行解不一定是最短路径,所以节点放入队列时的条件要有所修改,之前的visit数组保存的是是否访问过当前节点,那现在到达一个节点的状态有很多,所以visit数组的定义要做出改变,可以表示访问i,j时的转折次数。这是这道题能用来求可行解的关键。另外只有转折数小于等于当前转折次数的才能放入,因为进入一个点转折数等于是没问题的,而且可能换一个方向就能通过了。

WA了很多次,自己太急躁了,应该多想几组样例试一下的,要锻炼自己想样例的习惯。

代码实现:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <limits.h>
#define MAX 1010

using namespace std;

//节点状态
struct node{
    int x,y;
    int dis;
    int times;
};
int N,M;
int times;
int x1,y1,x2,y2;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
//访问i,j时的转折次数
int visit[MAX][MAX];
int grid[MAX][MAX];
bool bfs();
int main()
{
    while( scanf("%d%d",&N,&M) ){
        if( N == 0 && M == 0 ){
            break;
        }
        memset(grid,0,sizeof(grid));
        for( int i = 1; i <= N; i++ ){
            for( int j = 1; j <= M; j++ ){
                scanf("%d",&grid[i][j]);
            }
        }
        scanf("%d",&times);
        while( times-- ){
            //每次都要初始化
            for( int i = 1; i <= N; i++ ){
                for( int j = 1; j <= M; j++ ){
                    visit[i][j] = INT_MAX;
                }
            }
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if( bfs() ){
                printf("YES\n");
//                grid[x1][y1] = 0;
//                grid[x2][y2] = 0;
            }
            else{
                printf("NO\n");
            }
        }
    }
    return 0;
}

bool bfs(){
    //不符合情况直接返回
    if( grid[x1][y1] != grid[x2][y2] ){
        return false;
    }
    else if( grid[x1][y1] == 0 || (x1 == x2 && y1 == y2) ){
        return false;
    }
    //起点放入,转折次数为0,初始方向定义为-1
    node a;
    a.x = x1;
    a.y = y1;
    a.dis = -1;
    a.times = 0;
    queue<node> Q;
    Q.push(a);
    while( !Q.empty() ){
        node tmp = Q.front();
        Q.pop();
        if( tmp.x == x2 && tmp.y == y2 ){
            return true;
        }
        for( int i = 0; i < 4; i++ ){
            int nx = dx[i]+tmp.x;
            int ny = dy[i]+tmp.y;
            //这里的判断条件失误让自己wa了很多次,最开始写成了grid[nx][ny]==grid[x2][y2],死活没绕过来
            if( nx >= 1 && nx <= N && ny >= 1 && ny <= M && (grid[nx][ny] == 0 || (nx == x2 && ny == y2)) ){
                node in;
                in.x = nx;
                in.y = ny;
                in.dis = i;
                in.times = tmp.times;
                //方向不同转折数++
                if( tmp.dis != -1 && in.dis != tmp.dis ){
                    in.times++;
                }
                //只有转折数小于等于(注意一定要等于)当前转折次数的才能放入,并且不能超过2
                if( in.times <= 2 && visit[nx][ny] >= in.times ){
                    visit[nx][ny] = in.times;
                    Q.push(in);
                }
            }
        }
    }
    return false;
}
时间: 2024-10-11 01:38:20

HDU_1175 连连看(BFS)的相关文章

HDU 1175 连连看 (BFS带方向的判定)

连连看 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 23172    Accepted Submission(s): 5710 Problem Description “连连看”相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其

HDU 1175 连连看(bfs + 剪枝)

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

HDU 1175 连连看(BFS)

题意解析:其实就是判断起始点能否到达终止点.如果起始点和终止点值不同,直接输出NO.bfs,dfs都行. 附加条件:①不能出边界 ②不能走值为0的点 ③路径不能转向两次以上 节点需要记录该点的坐标,方向,转向次数.下面是BFS代码(注意剪枝:超过两次的就不要再加入队列了) #include<iostream> #include<cstdio> #include<queue> #define M 1005 using namespace std; int G[M][M];

HDU1175连连看 BFS

没啥困难的,bfs模板题,注意一下剪枝 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <cstdlib> #include <list> #include <s

BFS学习总结

BFS学习总结 给你一个n*m的网格迷宫,迷宫中有些格子不能走,其他的格子都能走.然后给你起点与终点,问你从起点走到终点最少需要多少步? 上面的问题就是一个典型的BFS问题,对于这类问题来说,只要你掌握了这类问题的关键思想,其实他们都是可以用类似的思路来做的. 你可以把BFS问题想象成:从一个父亲(起点状态)生儿子(后继状态),儿子又生孙子(后继状态)的过程,只要这个家族中出生了一个满意的后代(终点状态),这个家族就不生了. 但是如果这个家族中有两个完全一样的人出生(他们的辈分不一定相同),那么

HDU 1175 连连看(BFS)

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

hdu 1175(BFS) 连连看

题目在这里:http://acm.hdu.edu.cn/showproblem.php?pid=1175 大家都很熟悉的连连看,原理基本就是这个,典型的搜索.这里用的是广搜. 与普通的搜索比不同的是要求转折的线不能转折超过两次,就是在结构体中多开一个step(储存转折的次数)和一个dir(记录此刻的方向) 方向初始为-1,当行走一步后的方向与走之前不同的时候,step就应该加一, 然后还要注意的是为了保证得到的是所有的路线中转折次数最小的,这里的visit数组要用来保存每个点的最小转折次数, 所

HDU(1175),连连看,BFS

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1175 越学越不会,BFS还是很高级的. 连连看 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 30994    Accepted Submission(s): 7694 Problem Description “连 连看”相

杭电 HDU ACM 1175 连连看(麻烦的bfs)

连连看 Time Limit:10000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u SubmitStatusPracticeHDU 1175 Description "连连看"相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去.不好