1 条题解

  • 0
    @ 2026-3-17 18:01:53

    🧩 题目核心思路

    这是一道状态模拟 + 循环检测的经典题:

    • 两个角色(农夫F、牛C)都按固定规则移动:能走就走,不能走就顺时针转90°
    • 每分钟同时移动,只有在移动结束后同格才算相遇
    • 若状态(F的位置+方向、C的位置+方向)重复出现,说明进入循环,永远追不上,输出0

    📌 代码逐段解析

    1. 数据结构与全局变量

    #include<bits/stdc++.h>
    using namespace std;
    struct entity {
        int x,y,direction; // 坐标(x,y) + 方向(0北,1东,2南,3西)
    };
    int dx[4] = {-1, 0, 1, 0}; // 方向对应的x增量
    int dy[4] = { 0, 1, 0,-1}; // 方向对应的y增量
    int maps[12][12];          // 12x12地图(含边界障碍)
    int mark[12][12][4][12][12][4]; // 状态标记:C(x,y,dir) + F(x,y,dir)
    
    • entity 结构体统一存储角色的位置和方向
    • dx/dy 数组把方向映射为坐标变化(北:x减1,东:y加1…)
    • maps 用1表示障碍,0表示可走,边界也设为障碍
    • mark 是6维数组,用来记录是否出现过相同状态,避免无限循环

    2. 辅助函数

    bool judge(entity a,entity b) {
        return (a.x==b.x && a.y==b.y); // 判断是否同格
    }
    void print(entity a) {
        cout<<a.x<<" "<<a.y<<" "<<a.direction<<endl; // 调试用
    }
    
    • judge 只判断坐标是否相同,方向不影响相遇判定

    3. 主函数:输入与模拟

    int main() {
        entity c,f;
        // 读入10x10地图
        for(int i=1; i<=10; i++) {
            for(int j=1; j<=10; j++) {
                char ch; cin>>ch;
                if(ch=='C') {c.x=i; c.y=j; c.direction=0;} // 牛初始方向北
                if(ch=='F') {f.x=i; f.y=j; f.direction=0;} // 农夫初始方向北
                if(ch!='*') continue;
                maps[i][j] = 1; // 障碍标记为1
            }
        }
        // 给地图四周加障碍(12x12的边界)
        for(int i=0; i<=11; i++) {
            maps[i][0] = maps[i][11] = maps[0][i] = maps[11][i] = 1;
        }
    
        int step = 0;
        // 循环直到相遇或状态重复
        for(step = 0; !judge(c,f); step++) {
            // 状态重复 → 循环,输出0
            if(mark[c.x][c.y][c.direction][f.x][f.y][f.direction]) {
                cout<<0;
                return 0;
            }
            // 标记当前状态已出现
            mark[c.x][c.y][c.direction][f.x][f.y][f.direction] = 1;
    
            // 计算下一步坐标
            int cx = c.x + dx[c.direction];
            int cy = c.y + dy[c.direction];
            int fx = f.x + dx[f.direction];
            int fy = f.y + dy[f.direction];
    
            // 牛的移动逻辑
            if(maps[cx][cy]) { // 前方是障碍 → 转向
                c.direction = (c.direction + 1)%4;
            } else { // 能走 → 前进
                c.x = cx; c.y = cy;
            }
            // 农夫的移动逻辑(和牛完全一样)
            if(maps[fx][fy]) {
                f.direction = (f.direction + 1)%4;
            } else {
                f.x = fx; f.y = fy;
            }
        }
        // 相遇时输出步数
        cout<<step<<endl;
        return 0;
    }
    

    ⚠️ 关键细节

    1. 方向定义:0=北(↑)、1=东(→)、2=南(↓)、3=西(←),(dir+1)%4 实现顺时针转90°
    2. 状态唯一性mark 数组记录 (Cx,Cy,Cdir,Fx,Fy,Fdir),只要状态重复,就说明进入循环,永远追不上
    3. 同时移动:先算好两者的下一步,再同时更新位置,避免“先动者影响后动者”
    4. 边界处理:把10x10地图扩展成12x12,四周全设为障碍,简化“不能走出地图”的判断

    P1518 [USACO2.4] 两只塔姆沃斯牛 The Tamworth Two

    信息

    ID
    4540
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者