题解 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.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;
}
望题解过审。