吴昊品游戏核心算法 Round 16 —— 吴昊教你玩口袋妖怪 第七弹 小茂道馆

 

  小茂啊!让我怎么说你好呢?有时候,永远的对手其实就是永远的朋友吧!任天堂在人物的设定中,小茂总给人一种时而傲娇,时而那么霸气,时而又那么让人讨厌的一种角色。不过,作为每次的口袋妖怪天王战的霸主小茂,总给人一种不可一世的感觉(在口袋妖怪金银的深山中,曾经隐藏着一个比小茂还要强悍的一个角色,没有名字,就是一登场就是一个81级的皮卡丘的那个人)

  这个道馆也比较华丽,给人一种跳舞机的感觉,地板上到处都是箭头,和龙系道馆不一样,这个道馆,我们的方向不是主观可控的了,我们需要遵循着箭头的方向前进。不过,注意到箭头之间还是有缝隙的(也就是存在有空地的地板),我们可以选择一个初始的方向(后面的方向可以说仍然是不可控制的)

  当然,和龙系道馆的场景一样,这里的场景在口袋妖怪中也是随处可见的:

 

  这里是一个场景,注意到黄颜色的正方形区域,该点可以作为一个吸收装置,你如果被转移到那里,你将会被吸收,之后,你会停下来,再进行下一步的走动。

 

  更多的时候,这样的吸收装置是没有的,如图所示,在这种场景中,吸收装置少了许多,更多地,是被一堵墙给代替了。当然,在这里,空地还是存在的,我们这里要做的是,进一步化简!我们消除空地的存在,为什么呢?唯有如此,才能将人的可控制性降低到没有,一个输入才能唯一地对应一个输出,所以,我们将其简化为如下的数学模型:

 

  如图所示,我们的主角从某一个位置(第一行的某一个确定的位置)进入小茂道馆,然后,在一个过程中,达到两种情况中的一个:(1)在某一点被拱出去(2)被吸入一个有限的循环之中(地图被抽象为一个完整的二维数组,其中,完整的含义是不留下任何的空地),N,E,S,W分别代表箭头的指向,是北,东,南还是西。

  Input:第一行三个数字,前面两个代表地图的规模(W*H,最后一个代表我们的主角是从第一行的哪一列开始移动。

  Output:作为一个模拟的问题,我们最终需要知道我们的主角最后怎么了?是陷入了循环的漩涡呢?还是走出了这个漩涡,以至于可以和小茂一决雌雄呢?由于整个地图布满了箭头,所以没有必要考虑AI了,唯一的AI也许就是想想我们的主角小智应该从第一行的哪一列滑行,当然,这一点的话,由于输入和输出都是一一映射的,貌似也没有讨论的价值了。

  Solve:

  Highlights:关于循环的判定是本问题的独特亮点,因为只要是位置上有相同的话,就说明必然存在循环了!该位置就是循环的起始点。考虑到这一步,我们就可以想到利用一个字符数组存储所有的经过,利用strstr函数进行逐一的比对,最重要的还是要找到循环的首元素的下标。

  

 1  #include<stdio.h>
 2   // 由于需要字符串函数strstr处理,这里开启头文件
 3  #include< string.h>
 4  int main()
 5 {
 6    // 定义地图,以及记录位置的信息:(方向+位置)
 7    char grid[ 11][ 12],record[ 303],record_now[ 4];
 8   int row,column,start,indicator,a,row_now,column_now,loop,step,step2;
 9   while(scanf( " %d%d%d ",&row,&column,&start)== 3&&(row!= 0||column!= 0||start!= 0))
10  {
11    // 数组清空
12    strcpy(record, "");
13    // 记录循环节的大小
14    step= 0;
15    // 读入一个地图
16     for(a= 0;a<row;a++)
17    scanf( " %s ",grid[a]);
18    // 第一格无所谓,无论标注什么都是可以的
19    record_now[ 0]= 48;
20   record_now[ 1]= 48+start- 1;
21   record_now[ 2]= ' E ';
22   record_now[ 3]= ' \0 ';
23    // 记录数组的下标
24    indicator= 0;
25   row_now= 0;
26   loop= 0;
27   column_now=start- 1;
28    // 越界的话,就退出
29     while(row_now>= 0&&row_now<=row- 1&&column_now>= 0&&column_now<=column- 1)
30   {
31    // 如果没有出现循环的话,分别对以下四种情况进行处理
32      if(strstr(record,record_now)==NULL)
33    {
34     strcpy(&record[indicator],record_now);
35     indicator+= 3;
36     step++;
37      if(grid[row_now][column_now]== ' N ')
38     {
39      row_now--;
40      record_now[ 0]--;
41     }
42      else  if(grid[row_now][column_now]== ' S ')
43     {
44      row_now++;
45      record_now[ 0]++;
46     }
47      else  if(grid[row_now][column_now]== ' E ')
48     {
49      column_now++;
50      record_now[ 1]++;
51     }
52      else
53     {
54      column_now--;
55      record_now[ 1]--;
56     }
57    }
58    // 如果循环的话,确定循环的首元素的位置,将loop置1
59      else
60    {
61     step2=(indicator-(strstr(record,record_now)-record))/ 3;
62     loop= 1;
63      break;
64    }
65   }
66    if(loop)
67    printf( " %d step(s) before a loop of %d step(s)\n ",step-step2,step2);
68    else
69    printf( " %d step(s) to exit\n ",step);
70  
71  }
72   return  0;
73 }

转载于:https://www.cnblogs.com/tuanzang/archive/2013/04/01/2993057.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值