Codeforces 769C

很久没有发题解,今天这题卡了下百度没看到相关题解,最后还是看了官方题解才找到原本思路的bug过的。

题意:给出一个二维迷宫,*表示墙,. 表示路,X表示起点,问一个长度为k的路径,从X出发并且回到X,且路径字典序最小。如存在输出路径(方向按U、D、L、R表示,英文首字母),不存在则输出IMPOSSIBLE。

 

解题思路(wa在第49个case):

显然按照字典序,方向优先级D>L>R>U。随便弄了几组样例发现通常情况下,当所走路径长度达到一半的时候,原路返回比绕一个圈更优,比如LLUDRR优于LLURRD,于是很草率的决定后一半的路径全为原路返回。

特殊判断当k为奇数或者四个方向都无法前往时输出IMPOSSIBLE。

wa了后先是想了比较久都没找到反例,看了官方题解后一下子就找到了,如下:(原本反例有误,已修正)

7 4 18
..X.
....
....
....
.**.
....
*b..

按上面的算法,当走到"b"的时候,因为路径长度计数到9,也就是18的一半,开始原路返回(即下一步为U),但其实再往右、右、上、上、上……(下一步为R)更优,且路径长度亦为18。

思路纠正:

先广搜出X到所有其它点的最短距离,遍历点时按优先级访问,当下一点到起点的最短距离大于k-cnt时,跳过。

先是奇怪地CE了一发,原因是queue<pair<int,int>>q;这句定义报错,两个>符号要分开。(好吧vs上面没有这个问题,语言编译系统不一样)

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
const int N=1e3+10;
int n,m,k,cnt,x,y,tx,ty,dis[N][N];
int dx[]={1,0,0,-1},dy[]={0,-1,1,0};
char g[N][N],res[N*N],dir[]="DLRU";
bool vis[N][N];
queue<pair<int,int>>q;
bool check(int tx,int ty){
    return tx>=0&&tx<n&&ty>=0&&ty<m&&g[tx][ty]!='*';
}
void init(){
    memset(vis,0,sizeof(vis));
    while(!q.empty()) q.pop();
    q.push(make_pair(x,y));
    vis[x][y]=true;
    while(!q.empty()){
        pair<int,int>tmp=q.front();q.pop();
        int tx=tmp.first,ty=tmp.second;
        for(int i=0;i<4;i++){
            int nx=tx+dx[i],ny=ty+dy[i];
            if(check(nx,ny)&&!vis[nx][ny]){
                q.push(make_pair(nx,ny));
                dis[nx][ny]=dis[tx][ty]+1;
                vis[nx][ny]=true;
            }
        }
    }
}
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d%d",&n,&m,&k)){
        cnt=0;
        for(int i=0;i<n;i++){
            scanf("%s",g[i]);
            for(int j=0;j<m;j++) if(g[i][j]=='X')
                x=i,y=j;
        }
        if(k&1){
            puts("IMPOSSIBLE");
            continue;
        }
        init();
        bool flag=true;
        while(flag){
            flag=false;
            for(int i=0;i<4;i++){
                tx=x+dx[i],ty=y+dy[i];
                if(check(tx,ty)&&dis[tx][ty]<=k-cnt){
                    flag=true;
                    res[cnt++]=dir[i];
                    x=tx,y=ty;
                    break;
                }
            }
            if(cnt==k) break;
        }
        if(!flag) puts("IMPOSSIBLE");
        else{
            res[k]='\0';
            puts(res);
        }
    }
    return 0;
}

 

posted @ 2017-03-14 11:35  轶辰  阅读(424)  评论(0编辑  收藏  举报