这道题分为两部分,一部分在于是否能两个人互相撞上,另一部分在于两个人要走多少步才能撞上。
很惭愧,虽然ac了,但是主要原因是数据卡的很松,第一部分是靠判断它的步数如果大于多少则不能撞上这样猜过去的
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int pos[20][20]; //边界外处为0(屏障)
long long mx = 1e5; //暴力不在=-=
void js(){
printf("!");
}
int judge(int fx,int fy,int nx,int ny){
if(pos[fy+1][fx]==0&&pos[fy-1][fx]==0&&pos[fy][fx+1]==0&&pos[fy][fx-1]==0)
return 1;
if(pos[ny+1][nx]==0&&pos[ny-1][nx]==0&&pos[ny][nx+1]==0&&pos[ny][nx-1]==0)
return 1;
return 0;
}
int main(){
int fx,fy,nx,ny; //农民和牛的坐标位置
for(int i = 1;i<=10;i++)
for(int j = 1;j<=10;j++) {
char a;
cin >> a;
if (a == '.')
pos[i][j] = 1; //1可通行,0不能
else if (a == '*')
pos[i][j] = 0;
if (a == 'F') {
fx = j;
fy = i;
pos[i][j] = 1;
}
if (a == 'C') {
nx = j;
ny = i;
pos[i][j] = 1;
}
}
if(judge(fx,fy,nx,ny)){
printf("0");
return 0;
}
int sf = 1,sn = 1; //用一个标志表明,他们现在要朝哪边转
for(int b = 1;;b++){
if(sf==1){ //北走
if(pos[fy-1][fx])
fy--;
else
sf++;
}
else if(sf==2){
if(pos[fy][fx+1])
fx++;
else
sf++;
}
else if(sf==3){
if(pos[fy+1][fx])
fy++;
else
sf++;
}
else if(sf==4){
if(pos[fy][fx-1])
fx--;
else
sf=1;
}
if(sn==1){ //北走
if(pos[ny-1][nx])
ny--;
else
sn++;
}
else if(sn==2){
if(pos[ny][nx+1])
nx++;
else
sn++;
}
else if(sn==3){
if(pos[ny+1][nx])
ny++;
else
sn++;
}
else if(sn==4){
if(pos[ny][nx-1])
nx--;
else
sn = 1;
}
if(nx==fx&&ny==fy){
printf("%d",b);
return 0;
}
if(b>mx){
printf("0");
break;
}
}
}
//这道题不知道什么情况下才不会撞上,所以我们只能判定,牛或者农民的出生点被围住了
//牛要么移动要么转弯
然后研究了一下题解的做法,其实是有点类博弈的思想,如果二者会同时回到一种状态,那么说明他们不会再相遇了,因为这时候他们已经陷入了一种对称性的状态,也就是说,如果二人能相遇,那么一定处于一种线性关系上,由此可判定,如果二人无法相遇,那么一定陷入了一种循环中
farmer.x+farmer.y∗10+cow.x∗100+cow.y∗1000+farmer.facing∗10000+cow.facing∗40000
以这个值作为一种vis循环,这种做法我觉得是一种方向移动上非常经典的移动标志