[2010山东省第一届ACM大学生程序设计竞赛]——Fairy tale

时间:2022-09-10 14:51:26
Fairy tale

题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2156

题目描述

It is said that in a school’s underground, there is a huge treasure which can meet any desire of the owner.
The Spy Union (SU) is very interest in this legend. After much investigation, SU finally get the answer and let the youngest spy sneak into the school. That’s why Saya is now here.
Today, Saya found the entrance eventually.
She enters the entrance, and found her in a fairy-tale world.
“Welcome!” says a fairy, “I am Ivan. My responsibility is to protect the treasure, and give it to the one who have the ability to own it.”
Then Ivan gives Saya three problems.
With your help, Saya finished the first and the second problem (Problem H and I). Here comes the third. If Saya can solve this problem, the treasure belongs to her.
There is a big maze protecting the treasure. You can assume the maze as an N*N matrix while each element in the matrix might be N (North), S (South), W (West) or E (East). At first, Saya is at the element (1, 1) – the north-west corner, and the treasure is at (N, N) – the south-east corner.
The designer have enchant to this matrix, so that the treasure might move from time to time respecting the following rules:
Suppose the treasure is in an element which marked with E. The treasure might eastward move a cell after a unit time. It is similar to S, W and N.
After a unit time, all the mark will change: E to W, W to S, S to N, and N to E. In another word, suppose an element which marked with E at time 0. At time 1, it might change to W, change to S at time 2, change to N at time 3, change to E at time 4, and so on.
Saya doesn't know the initial status of the marks. She is affected by this rule, but she decides to do something more.
Ivan gave Saya a special prop which called Riki. With Riki’s help, she can get the position of the treasure.
In each unit time, Saya will do all of the following three things:
Firstly, she will check the treasure’s position with Riki.
Secondly, she will move follow the designer’s magic the same with the treasure.(If no element exists in the direction of movement,the movement will be cancelled.)
Thirdly, Saya can either move to one direction (N, S, E, and W) a cell or stay there. Saya prefers to be closer with the treasure; if there are many ways with the same geometrical distance, Saya prefers to stay there than move, prefer E than W, W than N, and N than S. Here we should use the position checked at the first step.
You are given the size of the matrix and all the marks of the elements at time 0. Your task is to simulate Saya and the treasure’s movement, and then tell Saya the result.
输入
The input consists of several test cases.
The first line of input in each test case contains one integer N (0<N≤30), which represents the size of the matrix.
Each of the next N lines contains a string whose length is N, represents the elements of the matrix. The string only consists of N, E, W and S.

The last case is followed by a line containing one zero.


输出
For each case, print the case number (1, 2 …) and the result of Saya’s explore.
If Saya can get the treasure at step x (x≤100)(that means at the begainning of time x, Saya and the treasure stay in the same cell), print “Get the treasure! At step x.”.
If after simulating x (x≤100) steps, you found out that Saya can't get the treasure, print “Impossible. At step x.”
If you have simulated 100 steps but don’t know whether Saya can get the treasure, print “Not sure.”

Your output format should imitate the sample output. Print a blank line after each test case.


示例输入
5
EWSSE
NNENN
EENNE
SWSEW
NSNSW

0
示例输出
Case 1:

Get the treasure! At step 12.


提示
Q&A
Q: How can I know it’s impossible for Saya to get the treasure?

A: Suppose at time 5, Saya at (1, 1) while the treasure at (2, 2); at time 13, Saya at (1, 1) while the treasure at (2, 2) again. Since both Saya and the treasure go to the same place and have the same direction again, it is a loop, and they will just repeats the moves forever. So at time 13, we can judge it is impossible.


折腾了好久,终于折腾出来了,%>_<%~

这道题,当时原题重放的时候,直接被英文击倒,压根就没看。。。

比赛结束了,开始看一看,一道模拟题,模拟题向来。。呵呵。。。。


题目大意:

一个人在一个迷宫中寻宝,人初始位置左上角,宝藏在右下角。

迷宫每一个各自都有一个标记——E、S、W、N,象征着东、南、西、北。

1.首先来说一下宝藏的移动:

每一秒钟,宝藏会跟着地图的标记走,比如当前地图标记为E,宝藏会向东移动一格,

如果不能走,会停留在原地(如果到了边界,比如0,0位置需要向上走,出迷宫了,所以不走,停留在原地。)

上述那一段跟一道HDU题目特别像:http://blog.csdn.net/lttree/article/details/22398987

2.宝藏的走法说完了,现在说一说人的走法:

人从左上角出发,每一秒钟要走两个步骤:第一步,同宝藏一样,按照地图的格子内容行走,限制也同宝藏,不能走就停留在原地;第二步,喜好行走,就是按照人的意愿行走,什么意愿?拿宝藏的意愿,当然要靠近宝藏了。按初始状态来说,人的意愿肯定是向右下方行走啦。题目中也给出了意愿方案:E→W→N→S,当然也可以停留在原地不走。

简单的来说人第一步骤只能根据地图指示走,第二步骤有五种选择(4个方向+停留原地)

3.人和宝藏都说完了,再说说地图的规则:

这个地图是被附魔了的地图,它的格子并不会永远都一样,

每过一秒就会改变,但是改变是有规律的:E→W→S→N→E,

就是加入2,3这个位置格子第0秒为E,第一秒就变成W,第二秒变成S,第四秒又变回E。。。

4.最后,说一说怎么终止:

这道题终止条件有3个:

①找到宝藏,输出步数。

②陷入循环,就是人的位置,宝藏的位置,还有相对时间均相同,则代表陷入循环,输出陷入循环时的步数。

③步数大于等于100了,就不需要继续走,退出来。


(⊙v⊙)嗯,题意就是这样。。。。需要消化一阵。。。o(╯□╰)o。。。

我因为做过那个机器人的题目(上面超链接的),所以感觉是搜索。。但是发现。。这道题貌似不一样,不是搜索。

后来,听YM说是模拟题,按着模拟来,一步步来,

对于地图的处理,我开始想一个地图,然后每秒两个for循环,对地图整体变化(变成另一个地图了)

后来,觉得地图总共最多就4种,大不了建4个地图,不需要每秒都变化了,但是每一步,人和宝藏走哪个地图,需要判断,加个switch,代码量无限上涨啊。。。

最后,发现我只需要管当前走的那个格子的标记,就可以了,不需要将整张地图给算出来。所以还是一个地图。

地图问题搞定了,存储就按照E→0 W→1 S→2 N→3,这样它的格子代表的方向就与时间有关。time%4

再有一点要说的就是,判断是否陷入循环,不仅要使4个坐标相同,还要让time%4的值相同,

为什么?就是坐标点相同后,相应位置地图的标记当然也要相同在可以。(搜索中剪枝常用到这)


大体就是这样了,终于做完了 。

下面代码有些解释的地方:

对于时间变量,我用time,在codeblock上没有问题,但是提交会错误,因该是不能定义这个类型的。。

像max,min,map什么的都谨慎使用啊。

在输入地图上我用了cin,造成了输入输出很乱,有的地方scanf,有的地方cin......

因为scanf("%c",&c)会把后面回车也读进去,造成混乱。。所以就用了cin。。

也可以在每一行输入完要输入下一行前,再次输入一个c,这样可以把回车读掉,

但是在输入行后面的回车也要单独处理.....

详见代码    /*2*/和/*1*/ 选一个,用/*1*/的话,三个都要加上去。


#include <stdio.h>
#include <iostream>
using namespace std;
// n地图大小,time记录时间,x,y记录人得位置,t_x、t_y宝藏位置。
int n,ttime,x,y,t_x,t_y,Map[31][31];
int dis[4][2]={0,1,0,-1,1,0,-1,0}; // 地图变化规律E→W→S→N→E
int dis_p[4][2]={0,1,0,-1,-1,0,1,0}; // 喜好行走规律E→W→N→S
bool re; // 判断是否转圈
struct Coor
{
int px,py,tx,ty,sp;
}cr[1001];

// 绝对值函数
int abs(int x)
{
return x<0?-x:x;
}
// 判断是否出界
bool outMap(int x,int y)
{
if(x<0 || y<0 || x>=n || y>=n) return 1;
return 0;
}
// 判断两个位置哪个离宝藏近
bool better(int x,int y,int xx,int yy)
{
return (x-t_x)*(x-t_x)+(y-t_y)*(y-t_y) < (xx-t_x)*(xx-t_x)+(yy-t_y)*(yy-t_y);
}
// 判断该步是否曾走过
bool judge_re(void)
{
int i;
for (i=0;i<ttime;++i )
if (cr[i].px==x && cr[i].py==y && cr[i].tx==t_x && cr[i].ty==t_y && cr[i].sp==ttime%4 )
{
re=true;
return true;
}
cr[i].px=x,cr[i].py=y,cr[i].tx=t_x,cr[i].ty=t_y,cr[i].sp=ttime%4;
return false;
}
// 模拟行走
bool step(void)
{
int s1,s2,xx,yy,txx,tyy;
s1 = (Map[x][y]+ttime)%4,s2 = (Map[t_x][t_y]+ttime)%4;
if ( x == t_x && y == t_y ) return true;
if ( judge_re() ) return false;

xx=x+dis[s1][0];
yy=y+dis[s1][1];
if ( !outMap(xx,yy) ) x = xx, y = yy; //第一步骤行走

xx = x,yy = y;
for ( int i = 0; i < 4; ++i ) //第二步骤行走
{
if ( outMap(x + dis_p[i][0], y + dis_p[i][1]) ) continue;
if ( better(x + dis_p[i][0],y + dis_p[i][1], xx, yy) )
{
xx = x + dis_p[i][0];
yy = y + dis_p[i][1];
}
}
x = xx, y = yy;

txx = t_x + dis[s2][0];
tyy = t_y + dis[s2][1];
if ( !outMap(txx, tyy) ) {t_x = txx;t_y = tyy;} //宝藏走
++ttime;
return false;
}



int main()
{
int i,j,test=1;
char c;
while(scanf("%d",&n)!=EOF)
{
/*1*/ scanf("%c",&c);
if(!n) break;
// 读入地图
for(i=0;i<n;++i)
{
for(j=0;j<n;++j)
{
/*1*/ scanf("%c",&c);
/*2*/ cin>>c;
switch(c)
{
case 'N':Map[i][j]=3;break;
case 'S':Map[i][j]=2;break;
case 'E':Map[i][j]=0;break;
case 'W':Map[i][j]=1;break;
}
}
/*1*/ scanf("%c",&c);
}
// 初始化
t_x=n-1,t_y=n-1;
ttime=0;
re=0;
x=0,y=0;

printf("Case %d:\n",test++);
while(ttime<100)
{
if ( step() )
{
printf("Get the treasure! At step %d.\n", ttime);
break;
}
if ( re )
{
printf("Impossible. At step %d.\n", ttime);
break;
}
if ( ttime == 99 )
{
printf("Not sure.\n");
break;
}
}
printf("\n");
}
return 0;
}