USACO Section 2.4 The Tamworth Two (BFS模拟)

用三维数组保存运动物体第一次处于x、y坐标和某方向时所用步数,同时记录当运动物体的路径和出现循环时的周期。这一步用BFS完成。

枚举两个运动物体路径中的公共位置,根据情况分类讨论。

有3种情况。

1,人和牛都处于循环路径中。即判断A+xa=B+y+b,用拓展欧几里德求解。

2,人和牛都不在循环路径中。即判断A=B。

3,人和牛只有一个在循环路径中。即判断A+xa=B。

/*
ID: kkkwjx1
PROG: ttwo
LANG: C++
*/
#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=15;
char grid[maxn][maxn];
struct Character
{
    int x,y;
    int dir,step;
    int period;
    int vis[maxn][maxn][4];
    vector<pair<int,pair<int,int> > > path;
    Character():dir(0),step(0)
    {
        memset(vis,-1,sizeof(vis));
    }
};
Character farmer,cow;
const int mv[4][2]= {-1,0,0,1,1,0,0,-1};
bool judge(int x,int y)
{
    return 0<=x&&x<10&&0<=y&&y<10&&grid[x][y]!='*';
}
void bfs(Character &actor)
{
    while(true)
    {
        if(actor.vis[actor.x][actor.y][actor.dir]!=-1)
        {
            actor.period=actor.step-actor.vis[actor.x][actor.y][actor.dir];
            return ;
        }
        actor.path.push_back(make_pair(actor.dir,make_pair(actor.x,actor.y)));
        actor.vis[actor.x][actor.y][actor.dir]=actor.step;
        int nx=actor.x+mv[actor.dir][0],ny=actor.y+mv[actor.dir][1];
        if(!judge(nx,ny))
            actor.dir=(actor.dir+1)%4;
        else
        {
            actor.x=nx;
            actor.y=ny;
        }
        ++actor.step;
    }
}
int e_gcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int ans=e_gcd(b,a%b,x,y);
    int temp=x;
    x=y;
    y=temp-a/b*y;
    return ans;
}

int meet()
{
    int ans=0;
    for(int i=0; i<farmer.path.size(); ++i)
    {
        for(int j=0; j<cow.path.size(); ++j)
        {
            if(farmer.path[i].second!=cow.path[j].second)
                continue;
            int a=0,b=0;
            if(farmer.path.size()-farmer.period<=i)
                a=farmer.period;
            if(cow.path.size()-cow.period<=j)
                b=cow.period;
            int res=-1;
            int A=farmer.vis[farmer.path[i].second.first][farmer.path[i].second.second][farmer.path[i].first];
            int B=cow.vis[cow.path[j].second.first][cow.path[j].second.second][cow.path[j].first];
            if(a&&b)
            {
                int x,y;
                int d=e_gcd(a,b,x,y);
                int c=-A+B;
                if(c%d!=0)
                    continue;
                d=c/d;
                x=abs(x*d);
                y=abs(y*d);
                res=min(A,B)+max(x*a,y*b);
            }
            else if(a==0&&b==0)
            {
                if(A==B)
                    res=A;
            }
            else
            {
                if(a==0)
                {
                    swap(a,b);
                    swap(A,B);
                }
                int Z=B-A;
                if(Z>=0&&Z%a==0)
                    res=B;
            }
            if(res!=-1)
            {
                if(ans==0||res<ans)
                    ans=res;
            }
        }
    }
    return ans;
}
int main()
{
    freopen("ttwo.in","r",stdin);
    freopen("ttwo.out","w",stdout);
    for(int i=0; i<10; ++i)
    {
        scanf("%s",grid[i]);
        for(int j=0; grid[i][j]; ++j)
        {
            if(grid[i][j]=='F')
            {
                farmer.x=i;
                farmer.y=j;
            }
            else if(grid[i][j]=='C')
            {
                cow.x=i;
                cow.y=j;
            }
        }
    }
    bfs(farmer);
    bfs(cow);
    int ans=meet();
    printf("%d\n",ans);
    return 0;
}


回答: 题目P1518 \[USACO2.4\] 两只塔姆沃斯牛是一道模拟题,题目要求判断Farmer John和两头牛是否会相遇。解题思路可以分为两种方法。一种方法是记录二者的状态,如果出现了与前面相同的状态则说明陷入了死循环。具体实现步骤可以使用数组来记录Farmer John和两头牛的坐标、方向等状态信息,然后判断是否出现了重复的状态。另一种方法是利用博弈的思想,如果二者会同时回到一种状态,那么说明他们不会再相遇了,因为这时候他们已经陷入了一种对称性的状态。通过判断是否存在一种线性关系,可以确定二者是否会相遇。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two](https://blog.csdn.net/TD123456q/article/details/125688037)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [洛谷P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two 题解 (C/C++)](https://blog.csdn.net/Jason__Jie/article/details/115027619)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [(移动方向状态标志)P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two题解](https://blog.csdn.net/m0_57221330/article/details/119980758)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值