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

题目描述

两只牛逃跑到了森林里。Farmer John 开始用他的专家技术追捕这两头牛。你的任务是模拟他们的行为(牛和 John)。

追击在 10 × 10 10 \times 10 10×10 的平面网格内进行。一个格子可以是:一个障碍物,两头牛(它们总在一起),或者 Farmer John。两头牛和 Farmer John 可以在同一个格子内(当他们相遇时),但是他们都不能进入有障碍的格子。

一个格子可以是:

  • . 空地;
  • * 障碍物;
  • C 两头牛;
  • F Farmer John。

这里有一个地图的例子:

*...*.....
......*...
...*...*..
..........
...*.F....
*.....*...
...*......
..C......*
...*.*....
.*.*......

牛在地图里以固定的方式游荡。每分钟,它们可以向前移动或是转弯。如果前方无障碍(地图边沿也是障碍),它们会按照原来的方向前进一步。否则它们会用这一分钟顺时针转 90 度。 同时,它们不会离开地图。

Farmer John 深知牛的移动方法,他也这么移动。

每次(每分钟)Farmer John 和两头牛的移动是同时的。如果他们在移动的时候穿过对方,但是没有在同一格相遇,我们不认为他们相遇了。当他们在某分钟末在某格子相遇,那么追捕结束。

读入十行表示地图。每行都只包含 10 个字符,表示的含义和上面所说的相同。保证地图中只有一个 F 和一个 CFC 一开始不会处于同一个格子中。

计算 Farmer John 需要多少分钟来抓住他的牛,假设牛和 Farmer John 一开始的行动方向都是正北(即上)。 如果 John 和牛永远不会相遇,输出 0。

输入格式

输入共十行,每行 10 个字符,表示如上文描述的地图。

输出格式

输出一个数字,表示 John 需要多少时间才能抓住牛们。如果 John 无法抓住牛,则输出 0。

样例 #1

样例输入 #1

*...*.....
......*...
...*...*..
..........
...*.F....
*.....*...
...*......
..C......*
...*.*....
.*.*......

样例输出 #1

49

提示

翻译来自NOCOW

USACO 2.4

1.题目分析

输入一张字符地图,有空地和障碍物以及边界,一个人追一头牛,
人和牛的运动规律相同:碰壁转向,不碰壁则按照现有方向前进一。
如果人可以追上牛则打印花费的时间,反之则输出0.

值得注意的是:人和牛的初始位置也要计入可运动的点。
函数调用时,如果需要改变实参的值,需要在形参前加引用符号&。

2.题目思路

计算人和牛运动的最大时间,作为人和牛能不能相遇的循环终止条件:
最大时间应该不超过:牛和人最多有10 * 10 * 4的平方种状态。

定义一个结构体表示人或者牛,四个参数:
name代表是人还是牛,towards代表当前朝向:1代表向北,2 代表东,3代表南,4代表西,初始均为1(题目要求初始是一路向北),x,y代表在二维数组中的位置。

定义一个移动函数:记录牛和人的坐标变化 ,
注意第二个参数必须要加引用符号&,将每轮的数据带出来。
形参有两个:数组和结构体。
大体思路是先判断人物朝向,再判断下一步是否碰壁,如果不碰壁则移动位置,反之则调转方向。

主函数:
定义二维数组存储地图,定义牛和人的结构体,定义花费的时间,
键入地图,记录牛和人的初始坐标给结构体,
值得注意的是:需要将牛和人将初始位置赋值为空地。

计算花费时间:
循环阶数的条件是,是否大于最大时间,先判断牛和人的坐标是否重合,重合则跳出循环,不重合则继续移动,牛和人分别调用移动函数,判断结束后时间加一。

最后,判断人是否遇到了牛,打印相应的结果即可。

3.代码实现

#include 

using namespace std;
//最大时间应该不超过:牛和人最多有10*10*4的平方种状态
#define MAX_TIME  10000

//定义一个结构体 name代表是人还是牛
typedef struct data {
    char name;
    //代表当前朝向:1代表向北,2 代表东,3代表南,4代表西,初始均为1
    int towards = 1;
    //代表当前坐标
    int x, y;
} cows;

//移动函数:记录牛和人的坐标变化 ,注意第二个参数必须要加引用符号&,将每轮的数据带出来
void move(char arr[10][10], cows &c) {
    //判断移动方向
    if (c.towards == 1) {
        //向北
        //判断是否碰壁
        if (arr[c.x - 1][c.y] == '.' && c.x - 1 >= 0) {
            //移动
            c.x -= 1;
        } else {
            //碰壁则转向
            c.towards = 2;
        }
    } else if (c.towards == 2) {
        //向东
        //判断是否碰壁
        if (arr[c.x][c.y + 1] == '.' && c.y + 1 < 10) {
            //移动
            c.y += 1;
        } else {
            //碰壁则转向
            c.towards = 3;
        }
    } else if (c.towards == 3) {
        //向南
        //判断是否碰壁
        if (arr[c.x + 1][c.y] == '.' && c.x + 1 < 10) {
            //移动
            c.x += 1;
        } else {
            //碰壁则转向
            c.towards = 4;
        }
    } else {
        //向西
        //判断是否碰壁
        if (arr[c.x][c.y - 1] == '.' && c.y - 1 >= 0) {
            //移动
            c.y -= 1;
        } else {
            //碰壁则转向
            c.towards = 1;
        }
    }
}

int main() {
    //定义二维数组存储地图
    char arr[10][10];
    //定义牛和人
    cows f, c;
    f.name = 'F';
    c.name = 'C';
    //定义花费的时间
    int times = 0;
    //键入地图
    for (int i = 0; i < 10; ++i) {
        for (int j = 0; j < 10; ++j) {
            cin >> arr[i][j];
            //记录牛和人的初始坐标,注意:并将初始位置赋值为空地
            if (arr[i][j] == f.name) {
                f.x = i;
                f.y = j;
                arr[i][j] = '.';
            }
            if (arr[i][j] == c.name) {
                c.x = i;
                c.y = j;
                arr[i][j] = '.';
            }
        }
    }
    //计算花费时间
    while (times < MAX_TIME) {
        //判断f,m是否重合
        if (f.x == c.x && f.y == c.y) {
            //重合即跳出循环
            break;
        } else {
            //不重合则继续移动
            //牛的移动
            move(arr, c);
            //人的移动
            move(arr, f);
        }
        times++;
    }
    //判断是否抓到了牛
    if (times == MAX_TIME) {
        //未抓到
        cout << 0;
    } else {
        //抓到了,打印花费的时间
        cout << times;
    }
    return 0;
}

你可能感兴趣的:(刷题go,go,go,算法,c++)