(移动方向状态标志)P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two题解

这道题分为两部分,一部分在于是否能两个人互相撞上,另一部分在于两个人要走多少步才能撞上。

很惭愧,虽然ac了,但是主要原因是数据卡的很松,第一部分是靠判断它的步数如果大于多少则不能撞上这样猜过去的

#include
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循环,这种做法我觉得是一种方向移动上非常经典的移动标志

你可能感兴趣的:(经典错题,算法,acm竞赛,c++)