[蓝桥杯][2014年第五届真题]兰顿蚂蚁(说实话,一发过,存在点代码疑问)

直接上代码吧,好水,这测试代码,比赛 是同一个测试吗?

http://www.dotcpp.com/oj/problem1429.html

 

问题:

题目如下:

兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。


平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。 
蚂蚁的头部朝向为:上下左右其中一方。 

蚂蚁的移动规则十分简单: 
若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格; 
若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。 

规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。 

蚂蚁的路线是很难事先预测的。 

你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。 



输入如下:

输入数据的第一行是  m  n  两个整数(3  <   m,  n  <   100),表示正方形格子的行数和列数。 
接下来是  m  行数据。 
每行数据为  n  个被空格分开的数字。0  表示白格,1  表示黑格。 

接下来是一行数据:x  y  s  k,  其中x  y为整数,表示蚂蚁所在行号和列号(行号从上到下增长,列号从左到右增长,都是从0开始编号)。s  是一个大写字母,表示蚂蚁头的朝向,我们约定:上下左右分别用:UDLR表示。k  表示蚂蚁走的步数。 



输出如下:

输出数据为一个空格分开的整数  p  q,  分别表示蚂蚁在k步后,所处格子的行号和列号。



代码思路如下:

这题 很水,一个暴搜索,就可以通过了。



问题:

但是我想问:如果真的出现了,循环怎么办?

此时就会产生一些数据:第一次的路过 step(firstNumber),路过之后的在此路过,也就是循环次数,还有一点就是 第一次路过到第一次循环的点的数目(xunhuanNumber)



循环的条件:进过该点 xunhuanNumber 次,之后 就会出现循环.(个人认为)



状态(颜色,方向,地点(Row,column))

关键:比如:a到b,途径三个点,如果状态相同,循环了三次之后,是不是就是第一次经过的样子?

因为如果不是的话,那么 条件中 在循环1~2次的时候,会转弯(1),在循环的途中会方向变化(2),修改过中间的点的变化.



这些都是问题,但是代码测试,却没有这个方面的测试用例。所以循环条件存在问题,求解。

 

代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

/*
蚂蚁的移动规则十分简单:
若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。

规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,
但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。

蚂蚁的路线是很难事先预测的。

你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。
*/

/// 出现第一次循环的步数 , 循环的次数 ,两种颜色 ,四个方向,二维表格[3~100]
/// vis 记录第一次循环的步数,xunhuan记录循环的次数
///四个方向 : 上左下右:0,1,2,3
int vis[2][4][105][105] , xunhuanNumber[2][4][105][105] , firstxunhuan[2][4][105][105], mp[105][105];
int color , direction ,  Row , column , n , m;
///保留数据
struct Node{
    int row , column;
}listNode[100050];

void change(){
     mp[Row][column] = (1+mp[Row][column])%2;
     ///黑色
     if(color == 1){
            switch(direction){
              case 0:column++;break;
              case 1:Row--;break;
              case 2:column--;break;
              case 3:Row++;break;
            }
         direction = (direction-1+4)%4;
     }else{
            switch(direction){
              case 0:column--;break;
              case 1:Row++;break;
              case 2:column++;break;
              case 3:Row--;break;
            }
         direction = (direction+1)%4;
     }

}

void display(){
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            printf("%d " , mp[i][j]);
        }
        printf("\n");
    }
}

void bfs( long step){
     ///更新当时的颜色
     color = mp[Row][column];
     ///保存数据
     listNode[step].row = Row;
     listNode[step].column = column;
     ///正常接收
     if( step == 0)
        return ;
     ///出现了循环现象:就是循环次数 = 出现第一个循环的步数
     if( vis[color][direction][Row][column] != 0 &&
         vis[color][direction][Row][column] == xunhuanNumber[color][direction][Row][column]){
        ///表示以第一次出现的步数到该点为一次循环
        int xunhuanNode = firstxunhuan[color][direction][Row][column] - step;
        ///求出循环中间的点
        Row = listNode[xunhuanNode + firstxunhuan[color][direction][Row][column]].row;
        column = listNode[xunhuanNode + firstxunhuan[color][direction][Row][column]].column;
        return ;
     }
     ///判断他是否出现了循环
     if(firstxunhuan[color][direction][Row][column] != 0){
        ///第一次循环 改变的点的数目
        if( vis[color][direction][Row][column] == 0 )
            vis[color][direction][Row][column] = firstxunhuan[color][direction][Row][column] - step;
     }
     ///表示该点出现过了
     firstxunhuan[color][direction][Row][column] = step;
     xunhuanNumber[color][direction][Row][column]++;
///     若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
///     若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。
     change();
//     printf("------------------------------\n");
//     printf("第 %d 步\n",step);display();printf("%d %d\n",Row, column);
//     printf("------------------------------\n");
     bfs( step -1 );
     return ;
}

int main()
{
    long step;
   while(~scanf("%d%d",&n,&m)){
       ///输入地图
       for(int i = 0;i<n;i++){
        for(int j=0;j<m;j++)
            scanf("%d",&mp[i][j]);
       }
       ///初始化数据
       memset(vis , 0, sizeof(vis));
       memset(xunhuanNumber , 0, sizeof(xunhuanNumber));
       memset(firstxunhuan , 0, sizeof(firstxunhuan));
       memset(listNode , 0, sizeof(listNode));
       char ch;
       scanf("%d %d %c %lld",&Row , &column , &ch , &step);
       if(ch=='U') direction = 0;
       else if(ch =='L') direction = 1;
       else if(ch == 'D') direction = 2;
       else direction = 3;
       bfs(step);
       printf("%d %d\n",Row , column);
   }
   return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值