poj1024

题目描述:给定走出一个迷宫的最短路径,再给出一个由这个最短路径算出来的解(一个墙的结合),现在要有设计程序判断该解是否正确。
正确的标准:最短路径为给出的最短路径且唯一,如果给出的解(墙的集合)组成的迷宫的最短路径比给定的最短路径长或短都不行,一定要一样长且只有给定的那一条路是最短路。
输入格式:多组数据,第一行为一个整数t,表示数据的组数
每组数据包括一个原始问题输入和一个原始问题输出。
原始问题输入就是给定的最短路径,格式如下:

  • 第一行是两个整数w和h,表示迷宫的宽度和高度,
  • 第二行是一行由四个字母(‘U’,’D’,’R’,’L’)组成的字符串,U表示向上走,D表示向下走,R表示向右走,L表示向左走。

原始问题输出就是一个墙的集合,格式如下:

  • 第一行一个整数n,表示有n个墙
  • 接下来是n行,每行四个整数,两个点的坐标,表示这两个点之间有一堵墙。

输出格式:输出CORRECT或者INCORRECT,表示原始问题输出正确或者不正确。

解题思路:一开始只想到了怎么判断最短路径是否唯一,但是不知道怎么判断墙是否多余,然后在discuss里面看到一个绝妙的算法,具体的想法如下:

  • 分别从起点到到终点和从终点到起点进行bfs,通过bfs分别算出从起点到每个点的最短距离dis1和从终点到每个点的最短距离dis2。
  • 把给定的最短路径所经过的点打上标记,再把所有墙两边的点打上标记
  • 然后对所有没有标记的点进行判断,如果存在一个点满足dis1+dis2==pathlen(给定的最短路径的长度),那么则最短路径不唯一
  • 然后判断是否有墙多余,枚举每个墙两边的点(分别记为a和b),如果从起点到a的距离加上从终点到b的距离和从终点到a的距离加上从起点到b的距离都大于pathlen,那么当前的墙是多余的。
  • 注意一个特殊情况!!!!如果出现一个被墙围起来的封闭区域,那么一定会有一个墙多余。但是bfs算不出来,需要进行特判。

下图是特殊情况
特殊情况

具体代码如下:
PS:传参数什么的好麻烦,看来下次要写结构体,然后把数据全部封装起来了,那样直接传结构体的地址就好了。

#include <cstdio>
#define MAXN 111

struct barrier{
    int x1, y1;
    int x2, y2;
};

void bfs(int startx, int starty, int dis[][MAXN], int w, int h, barrier *bar, int n);

int main(int argc, char const *argv[])
{
    int t; 
    for(scanf("%d", &t); t; --t) {
        bool vis[MAXN][MAXN] = {true};
        int  w, h, endx=0, endy=0;
        scanf("%d%d\n", &w, &h);
        bool fail = false;
        int  pathlen = 0;
        char ch;
        while(ch=getchar(), ch!= '\n'){
            switch(ch){
                case 'R': endx++; break;
                case 'U': endy++; break;
                case 'L': endx--; break;
                case 'D': endy--; break;
                default : break;
            }
            vis[endx][endy]=true;
            ++pathlen;
        }
        int n;
        scanf("%d", &n);
        barrier bar[MAXN*MAXN];
        for(int i=0; i<n; ++i){
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            bar[i].x1=x1; bar[i].y1=y1;
            bar[i].x2=x2; bar[i].y2=y2;
            vis[x1][y1]=true;
            vis[x2][y2]=true;
        }
        int dis1[MAXN][MAXN]={0}, dis2[MAXN][MAXN]={0};
        bfs(0, 0, dis1, w, h, bar, n); bfs(endx, endy, dis2, w, h, bar, n);
        ///条件一:判断最短路径是否符合要求
        for(int i=0; i<w; ++i){
            for(int j=0; j<h; ++j){
                if(!vis[i][j]&&dis1[i][j]+dis2[i][j]==pathlen){
                    fail=true;
                    break;
                }
            }
            if (fail){
                break;
            }
        }
        if (fail){
            printf("INCORRECT\n");
            continue;
        }
        ///条件二:判断是否有墙多余
        for (int i = 0; i < n; ++i) {
            int x1=bar[i].x1, y1=bar[i].y1;
            int x2=bar[i].x2, y2=bar[i].y2;
            if( (dis1[x1][y1]+dis2[x2][y2]>pathlen 
             && dis2[x1][y1]+dis1[x2][y2]>pathlen) ///主要条件
             || (dis1[x1][y1]==0 && dis2[x1][y1]==0) ///存在封闭区域
             || (dis1[x2][y2]==0 && dis2[x2][y2]==0) ){
                fail=true;
                break;
            }
        }
        if (fail) {
            printf("INCORRECT\n");
            continue;
        }
        printf("CORRECT\n");
    }
    return 0;
}

void bfs(int startx, int starty, int dis[][MAXN], int w, int h, barrier *bar, int n)
{
    bool vis[MAXN][MAXN]={false}; vis[startx][starty]=true;
    int  Qx[MAXN*MAXN], Qy[MAXN*MAXN], head=0, tail=0;
    Qx[tail]=startx; Qy[tail]=starty; ++tail;
    while(head<tail){
        int x=Qx[head], y=Qy[head]; ++head;
        const int dx[4]={0,1,0,-1};
        const int dy[4]={1,0,-1,0};
        for(int i=0; i<4; ++i){
            int px=x+dx[i];
            int py=y+dy[i];
            if(vis[px][py] || px<0||py<0||px>=w||py>=h) {
                continue;
            }
            bool isgo=true;
            for(int j=0; j<n; ++j){
                int x1=bar[j].x1, y1=bar[j].y1;
                int x2=bar[j].x2, y2=bar[j].y2;
                if( x1==x&&y1==y&&x2==px&&y2==py
                 || x2==x&&y2==y&&x1==px&&y1==py ) {
                    isgo=false; break;
                }
            }
            if(!isgo){ 
                continue;
            }
            dis[px][py]=dis[x][y]+1;
            vis[px][py]=true;
            Qx[tail]=px;
            Qy[tail]=py;
            ++tail;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值