题解 P1529 【回家 Bessie Come Home】

这道题总体来说并不难,纯模拟即可。唯一的难点就是判断无解。

我想了挺久愣是没想到什么好办法。然后我就动了点歪脑筋。

我们先来看一下这份没有判断无解情况的代码(我把他命名为代码67)。(思路与其他题解大体相同的,泥萌看不懂的话也可以去看其他题解的注释,然后他们判断无解的部分先忽略掉。

#include <cstdio>
#include <iostream>

const int N = 12;
const int dirx[]={-1,0,1,0},
          diry[]={0,1,0,-1}; 

char g[N][N];
int nx,ny;
int fx,fy;
int fdir;
int ndir;
int step;

bool in_side(int x,int y) {
    return (x>=1 && x<=10 && y>=1 && y<=10);
}

void Input() {
    std::ios::sync_with_stdio(false);
    for(int i=1; i<=10; i++) {
        for(int j=1; j<=10; j++) {
            std::cin>>g[i][j];
            if(g[i][j] == 'F') {
                fx=i,fy=j;
            }
            if(g[i][j] == 'C') {
                nx=i,ny=j;
            }
        }
    }
}

void Solve() {
    while(fx != nx || fy != ny) {
        step++;
        if(!in_side(fx+dirx[fdir],fy+diry[fdir]) 
        || g[fx+dirx[fdir]][fy+diry[fdir]] == '*') {
            fdir=(fdir+1)%4;
        } else {
            fx+=dirx[fdir],fy+=diry[fdir];
        }
        if(!in_side(nx+dirx[ndir],ny+diry[ndir]) 
        || g[nx+dirx[ndir]][ny+diry[ndir]] == '*') {
            ndir=(ndir+1)%4;
        } else {
            nx+=dirx[ndir],ny+=diry[ndir];
        }
    }    
    std::cout<<step;
}

int main(void) {
    Input();
    Solve();
    return 0;
}

这份代码交上去是$67$分,$TLE$了三个点。

是$TLE$而不是$WA$!原因显而易见:如果无解的话while循环会一直执行下去直到超时。

我们来分析一下这道题的性质:

  1. 如果有解就输出正确答案,如果无解就输出零
    • 不能超过时间限制
  2. 这道题有$1.6kAC$

从第三点,我们先肯定了这道题是可以$AC$的。

既可以$AC$,又不能超过时间限制。

我们就可以得出:如果一个数据在时间限制内得不到解,那这个数据一定无解! (当然,这个结论是在保证了代码67的时间按复杂度较优的情况下得出的。)

由这个结论我们进而可以推导出一个特别的无解判断方法:判断程序是否能在时间范围内得出解

我想到了两种方法:

第一种是分析程序的复杂度,然后从while循环的执行次数入手:

  • 代码67很明显是$o(n)$的。我们先贴一张图。

    很明显,如果while循环的执行次数超过了$10^7$,那就超时了。 于是只要在while循环里面加上一句if(step > 1e7) {printf("0");return ;}就完事了。

第二种是利用<ctime>这个库直接计算程序运行时间。但是我太菜了并不熟悉怎么用。有兴趣的同学自行百度咯。

于是我这不太正常的解法就$AC$了。

AC代码

#include <cstdio>
#include <iostream>

const int N = 12;
const int dirx[]={-1,0,1,0},
          diry[]={0,1,0,-1}; 

char g[N][N];
int nx,ny;
int fx,fy;
int fdir;
int ndir;
int step;

bool in_side(int x,int y) {
    return (x>=1 && x<=10 && y>=1 && y<=10);
}

void Input() {
    std::ios::sync_with_stdio(false);
    for(int i=1; i<=10; i++) {
        for(int j=1; j<=10; j++) {
            std::cin>>g[i][j];
            if(g[i][j] == 'F') {
                fx=i,fy=j;
            }
            if(g[i][j] == 'C') {
                nx=i,ny=j;
            }
        }
    }
}

void Solve() {
    while(fx != nx || fy != ny) {
        step++;
        if(!in_side(fx+dirx[fdir],fy+diry[fdir]) 
        || g[fx+dirx[fdir]][fy+diry[fdir]] == '*') {
            fdir=(fdir+1)%4;
        } else {
            fx+=dirx[fdir],fy+=diry[fdir];
        }
        if(!in_side(nx+dirx[ndir],ny+diry[ndir]) 
        || g[nx+dirx[ndir]][ny+diry[ndir]] == '*') {
            ndir=(ndir+1)%4;
        } else {
            nx+=dirx[ndir],ny+=diry[ndir];
        }
        if(step > 1e7) {
            printf("0");
            return ;
        }
    }    
    std::cout<<step;
}

int main(void) {
    Input();
    Solve();
    return 0;
}

望题解过审。

posted @ 2019-02-07 12:14  加固文明幻景  阅读(3)  评论(0编辑  收藏  举报  来源