hdu1175 连连看 dfs+剪枝

连连看

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 <cstdio>
#include <cstring>
using namespace std;

int maze[1010][1010];
bool vis[1010][1010];
int sx,sy,ex,ey;
bool flag;
int n,m,q;
int dicx[]={1,-1,0,0};
int dicy[]={0,0,1,-1};

void dfs(int x,int y,int dic,int turns){
    if(turns>2||flag) return;//转弯次数大于2或者已经找到就终止
    if(turns==2&&(x-ex)!=0&&(y-ey)!=0) return;//剪枝:判断两次转弯后是否与目标在同一直线上
    if(x==ex&&y==ey&&turns<=2){//搜索终点
        flag=1;
        return;
    }
    for(int i=0;i<4;++i){//搜索四个方向
        int xx=x+dicx[i];
        int yy=y+dicy[i];
        if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]) continue;//边界情况
        if(maze[xx][yy]==0||(xx==ex&&yy==ey)){
            vis[xx][yy]=1;
            if(dic==-1||dic==i)//如果在起点或者同向的情况turns不变及不转向,并将当前方向记为i
                dfs(xx,yy,i,turns);
            else
                dfs(xx,yy,i,turns+1);//否则turns+1
            vis[xx][yy]=0;
        }
    }
    return;
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0)
            break;
        memset(maze,0,sizeof(maze));

        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                scanf("%d",&maze[i][j]);

        scanf("%d",&q);
        for(int i=0;i<q;++i){
            scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
            memset(vis,0,sizeof(vis));

            flag=0;//初始化
            if(maze[sx][sy]==maze[ex][ey]&&maze[sx][sy])
                dfs(sx,sy,-1,0);//将初始方向设为-1 

            if(flag) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/lyj1/p/11516975.html

时间: 2024-10-12 18:57:45

hdu1175 连连看 dfs+剪枝的相关文章

HDU1175:连连看 [DFS]

题目链接:连连看 题意: 给出一张n*m的图,有q次询问,每次询问给出两个位置,问这两个位置是否能够相消 相消的条件: 1.两个位置可以用线相连且弯折度不超过2 2.两位置数字相同且不为0 分析: 用一个二维数组存储该位置的弯折度,注意剪枝顺序,详情见代码 一开始写dx[],dy[]的时候写成一维,却wa,不清楚为什么 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespa

hdu1175 连连看

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

ZOJ 1008 Gnome Tetravex (DFS + 剪枝)

Gnome Tetravex 题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=8 题意:有N*N个方格,每个方格分为上下左右四个部分,每个部分填数字.现在要求重排方块,使得每两个有边相连的方块对应的数字相同. 思路:就是一个简单的搜索,我想了个剪枝,将上下左右四个方向上每个数字对应的是哪几个方块记录下来,但是这个剪枝并没有起很大的作用,还是T了.后来才发现,如果有很多个方块是相同的,会重复搜索,所以需要将相同的方块一起处

UVA 10318 - Security Panel dfs 剪枝

UVA 10318 - Security Panel dfs 剪枝 ACM 题目地址:UVA 10318 - Security Panel 题意: 这题跟点灯的题目很像,点灯游戏选择一盏灯时会让它以及四周的灯改变状态. 但是我们有特殊的开开关技巧,它给出了改变状态的位置,而不是四周都改变. 问你从全部关着变成全部开着的最小开关步骤. 分析: 很明显,在一个位置上点两次或更多次是没有必要的,所以一个位置只有选择与不选择,用dfs即可,但如果暴力所有可能,复杂度是2^25,会超时,所以要剪枝. 由于

Cubes(DFS+剪枝)

题意:给一个数N,求N最少由多少个数的立方构成,并输出这些数. 做法:DFS + 剪枝,剪枝的边界很很很重要! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <stdio.h> int cub[400]; int ans[300]; int tp[300]; int n; int sum = 0x3f3f3f3f; //个数 void dfs(int le

hdu 4109 dfs+剪枝优化

求最久时间即在无环有向图里求最远路径 dfs+剪枝优化 从0节点(自己增加的)出发,0到1~n个节点之间的距离为1,mt[i]表示从0点到第i个节点目前所得的最长路径 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const

POJ 1564 Sum It Up (DFS+剪枝)

 Sum It Up Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5820   Accepted: 2970 Description Given a specified total t and a list of n integers, find all distinct sums using numbers from the list that add up to t. For example, if t = 4

EOJ1981 || POJ1011 经典dfs+剪枝+奇怪的数据

题目:EOJ1981 || POJ1011   经典dfs+剪枝+奇怪的数据 Description George took sticks of the same length and cut them randomly until all partsbecame at most 50 units long. Now he wants to return sticks to the originalstate, but he forgot how many sticks he had origi

HDOJ 5113 Black And White DFS+剪枝

DFS+剪枝... 在每次DFS前,当前棋盘的格子数量的一半小于一种颜色的数量时就剪掉 Black And White Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others) Total Submission(s): 194    Accepted Submission(s): 50 Special Judge Problem Description In mathematics,