The Tamworth Two

题意:有一个10×10的网格,网格的每一小格可以是障碍(*),空地(.),农夫(F)或者牛(C)。农夫和牛都有四个朝向,东南西北,初始情况下都朝北。二者都按照下面的规则来运动:如果向前走一步不是障碍或者走出网格,则向前走。否则顺时针改变朝向90度。每一分钟农夫和牛同时运动一步,求什么时候农夫和牛能够相遇在同一格。


解题思路

  1. 读入网格的状态,用数组maze[i][j]来保存,初始化为0,读到障碍的时候设为1。在读取过程中保存农夫和牛的初始状态。
  2. 农夫和牛的运动一定是有规律的,也就是在若干步(可以是0)以后陷入一个循环。
  3. 模拟农夫的运动,用farmer_state[i][j][k]来保存状态,全部初始化为-1。farmer_state[i][j][k] = x,代表在x分钟的时候,农夫走到坐标(i, j)处,并且朝向为k(北东南西分别为0,1,2,3)。
  4. 在某一时刻会发现farmer_state[i][j][k] != -1,那么就说明回到了前面的状态,此时农夫开始陷入循环,而且循环的长度就是此时的时间减去前面状态记录的时间。这样在模拟过程中可以记录农夫在何时陷入循环(farmer_repeat_from)和这个循环的长度(farmer_repeat_length)。
  5. 得到上述的farmer_state之后对其进行遍历,得到一个新的数组farmer_route[i][j],其中j取0和1。farmer_route[i][0]和farmer_route[i][1]分别代表农夫在经过i步之后所在的网格坐标(x, y)中的x和y。
  6. 对牛重复上述3~5操作即可得到相应的cows_state,cows_repeat_from,cows_repeat_length,cows_route。
  7. 求farmer_repeat_length和cows_repeat_length的最小公倍数,将其加上farmer_repeat_from和cows_repeat_from中较大的值,得到end_point。
  8. 对[0, end_point)这些时刻进行遍历,直到找到一个农夫和牛都处于同一网格的时刻(从farmer_route和cows_route中查找,相应的index用XXX_repeat_from和XXX_repeat_length计算得到)。end_point之后的时刻不需要进行处理,因为后面又会陷入另外一个循环(农夫与牛二者相对状态的循环)。

代码

/*
ID: zc.rene1
LANG: C
PROG: ttwo
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

enum directions{NORTH=0, EAST, SOUTH, WEST};

struct unit
{
    int i, j;
    int direction;
};

struct unit farmer, cows;
int maze[12][12];
int farmer_state[12][12][4];
int cows_state[12][12][4];

int GetCommonFactor(int a, int b)
{
    while ((a != 0)&&(b != 0))
    {
	if (a > b)
	{
	    a %= b;
	}
	else
	{
	    b %= a;
	}
    }
    return (a==0)? b:a;
}

void Move(struct unit *in)
{
    int new_i = (*in).i;
    int new_j = (*in).j;

    switch((*in).direction)
    {
	case 0:
	    new_i -= 1;
	    break;
	case 1:
	    new_j += 1;
	    break;
	case 2:
	    new_i += 1;
	    break;
	case 3:
	    new_j -= 1;
	    break;
	default:
	    break;
    }

    if (maze[new_i][new_j] == 0)
    {
	if ((*in).direction == 3)
	{
	    (*in).direction = 0;
	}
	else
	{
	    (*in).direction += 1;
	}
    }
    else
    {
	(*in).i = new_i;
	(*in).j = new_j;
    }
}

int main(void)
{
    FILE *fin, *fout;
    int i, j, k, count, temp;
    char *str = NULL;
    char lt;
    int **farmer_route, **cows_route;

    fin = fopen("ttwo.in", "r");
    fout = fopen("ttwo.out", "w");

    str = (char*)malloc(11*sizeof(char));
    memset(maze, 0, 12*12*sizeof(int));
    memset(farmer_state, -1, 12*12*4*sizeof(int));
    memset(cows_state, -1, 12*12*4*sizeof(int));

    for (i=1; i<11; i++)
    {
	fscanf(fin, "%s", str);
	for (j=1; j<11; j++)
	{
	    lt = str[j-1];
	    if (lt != '*')
	    {
		maze[i][j] = 1;
	    }
	    if (lt == 'F')
	    {
		farmer.i = i;
		farmer.j = j;
		farmer.direction = NORTH;
	    }
	    if (lt == 'C')
	    {
		cows.i = i;
		cows.j = j;
		cows.direction = NORTH;
	    }
	}
    }

    count = 0;
    while (farmer_state[farmer.i][farmer.j][farmer.direction] == -1)
    {
	farmer_state[farmer.i][farmer.j][farmer.direction] = count;
	count++;
	Move(&farmer);
    }
    int farmer_repeat_from = farmer_state[farmer.i][farmer.j][farmer.direction];
    int farmer_repeat_length = count - farmer_repeat_from;
    farmer_route = (int **)malloc(count*sizeof(int*));
    for (i=0; i<count; i++)
    {
	farmer_route[i] = (int *)malloc(2*sizeof(int));
	memset(farmer_route[i], 0, 2*sizeof(int));
    }
    for (i=1; i<11; i++)
    {
	for (j=1; j<11; j++)
	{
	    for (k=0; k<4; k++)
	    {
		temp = farmer_state[i][j][k];
		if (temp != -1)
		{
		    farmer_route[temp][0] = i;
		    farmer_route[temp][1] = j;
		}
	    }
	}
    }

    count = 0;
    while (cows_state[cows.i][cows.j][cows.direction] == -1)
    {
	cows_state[cows.i][cows.j][cows.direction] = count;
	count++;
	Move(&cows);
    }
    int cows_repeat_from = cows_state[cows.i][cows.j][cows.direction];
    int cows_repeat_length = count - cows_repeat_from;
    cows_route = (int **)malloc(count*sizeof(int*));
    for (i=0; i<count; i++)
    {
	cows_route[i] = (int *)malloc(2*sizeof(int));
	memset(cows_route[i], 0, 2*sizeof(int));
    }
    for (i=1; i<11; i++)
    {
	for (j=1; j<11; j++)
	{
	    for (k=0; k<3; k++)
	    {
		temp = cows_state[i][j][k];
		if (temp != -1)
		{
		    cows_route[temp][0] = i;
		    cows_route[temp][1] = j;
		}
	    }
	}
    }

    int greatest_common_factor = GetCommonFactor(farmer_repeat_length, cows_repeat_length);
    int greatest_common_multiple = farmer_repeat_length * cows_repeat_length / greatest_common_factor;
    int end_point = ((farmer_repeat_from > cows_repeat_from)?farmer_repeat_from:cows_repeat_from) + greatest_common_multiple;

    int farmer_index, cows_index;
    for (i=0; i<end_point; i++)
    {
	if (i < farmer_repeat_from)
	{
	    farmer_index = i;
	}
	else
	{
	    farmer_index = ((i - farmer_repeat_from) % farmer_repeat_length) + farmer_repeat_from;
	}

	if (i < cows_repeat_from)
	{
	    cows_index = i;
	}
	else
	{
	    cows_index = ((i - cows_repeat_from) % cows_repeat_length) + cows_repeat_from;
	}

	if ((farmer_route[farmer_index][0] == cows_route[cows_index][0])&&(farmer_route[farmer_index][1] == cows_route[cows_index][1]))
	{
	    break;
	}
    }

    if (i == end_point)
    {
	fprintf(fout, "0\n");
    }
    else
    {
	fprintf(fout, "%d\n", i);
    }

    return 0;
}
























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值