HUD1175 连连看 [dfs剪枝]

来源:互联网 发布:孤岛惊魂3优化 编辑:程序博客网 时间:2024/06/04 08:11

题目大意: 给定n,m和n行m列的数字矩阵,用整数表示不同的块,0表示通路。接下来q条询问,询问x1 y1 x2 y2之间是否满足连连看的规律。即用一条线(不超过两个弯)将两者连起来,且线段不能越过矩阵边界,不能穿过有块区域。

思路:

通过给定的第一个点开始dfs,可遍历求得通向第二点的路径,只需验证是否满足弯数小于等于2即可。

剪枝:当弯数大于2时,停止。当弯数等于2,但当前方向不指向终点方向,停止。

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;int m, n;int s[1005][1005];int dir[4][2] = {{0,1}, {0,-1}, {1,0}, {-1,0}};bool vis[1005][1005];int tx, ty;bool flag;void dfs(int x, int y, int d, int t){    if(flag) return;//已经找到解    if(t>2) return;//弯数大于2    if(!(x>0 && y>0 && x <= n && y <= m))        return;//越过矩阵边界    if(x==tx && y==ty)//找到解    {        flag = 1;        return;    }    if(t==2)//当弯数等于2时的剪枝    {        if(!(d==0&&ty>y&&x==tx || d==1&&ty<y&&x==tx || d==2&&tx>x&&y==ty || d==3&&tx<x&&y==ty))            return;    }    if(s[x][y] != 0) return;//不是通路    if(vis[x][y]) return;    vis[x][y] = 1;    for(int i = 0; i < 4; ++i)    {        int xx = x + dir[i][0], yy = y + dir[i][1];        if(d != i)            dfs(xx, yy, i, t+1);        else dfs(xx, yy, i, t);    }    vis[x][y] = 0; //一条路径的搜索停止,则将当前恢复的点vis重置}int main(){    while(~scanf("%d %d", &n, &m))    {        if(!n&&!m)            break;        for(int i = 1; i <= n; ++i)        for(int j = 1; j <= m; ++j)            scanf("%d", &s[i][j]);            //cin >> s[i][j];        int q;        cin >> q;        while(q--)        {            int x, y;            scanf("%d%d%d%d", &x, &y, &tx, &ty);            //cin >> x >> y >> tx >> ty;            if(x==tx && y==ty && s[x][y]!=0)            {                //cout << "NO" << endl;                printf("NO\n");                continue;            }            if(s[x][y]==s[tx][ty]&&s[x][y])            {                flag = 0;                memset(vis, 0,sizeof(vis));                for(int i = 0; i < 4; ++i)                    dfs(x+dir[i][0], y+dir[i][1], i, 0);                if(flag)                    printf("YES\n");                    //cout << "YES" << endl;                else                    //cout << "NO" << endl;                    printf("NO\n");            }            else printf("NO\n");        }    }    return 0;}


0 0
原创粉丝点击