直接上代码吧,好水,这测试代码,比赛 是同一个测试吗?
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;
}