山东省第一届ACM省赛 Fairy tale(模拟)

13 篇文章 0 订阅
8 篇文章 0 订阅

Problem Description

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.

Input

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.

Output

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.

Example Input

5
EWSSE
NNENN
EENNE
SWSEW
NSNSW

0

Example Output

Case 1:
Get the treasure! At step 12.

题目大意

晦涩难懂的题意,本来还以为是一道搜索题,迷迷糊糊的敲到一半发现根本不对。又重新回去读题,最后还是意念不够强大的搜了题解……
首先,可以简化为一个寻宝人探寻宝物的情景模拟,对于这个题目而言,地图、宝物位置、寻宝人位置都是变数。
变数1:地图,在地图中存在E、W、S、N四种字母分别代表方向,每经过一单位时间,字母就会发生改变。变化规律是E->W、W->S、S->N、N->E;
变数2:宝物位置,初始情况下,宝物位于地图的右下角,每经过一个单位时间,宝物可以按照所在位置指示的方向移动,如果在如果移动会超出边界的情况下,则静止;
变数3:寻宝人位置,初始情况下,寻宝人位于地图的左上角,寻宝人的移动过程有两次,且是在每单位时间内两种移动情况同时存在:
​ 1、第一次,寻宝人的移动规律相同于宝物,即随着所处位置指示的方向,若满足条件,则移动;
​ 2、第二次,寻宝人优先选择距离宝物最近的方向移动;若在四个方向下寻宝人与宝物的距离相等,寻宝人则选择不移动;若不是全相等,则遵从寻宝人的选择优先顺序,即E>W>N>S。

规则就是这些,然后结果的判断就是:
1、如果在100步之内,寻宝人寻到宝物(即寻宝人和宝物处于同一位置),则输出“Get the treasure! At step x.”;
2、如果在100步之内,发现寻宝人不可能寻到宝物(即寻宝人和宝物的相对位置复现了曾经出现过的状态),则输出 “Impossible. At step x.” ;
3、超出100步,输出“Not sure.”。

解题思路

就是一步一步的模拟,主要涉及一些转化的技巧
1、有关地图随时间的转化:将地图随时间变化的规律存放在数组中,数组可构建为dir1[4][2]={{0,1},{0,-1},{1,0},{-1,0}},并在输入数据时,将方向E、S、W、N相应处理为 0,1,2,3,在随时间变化时直接加上 step 再%4即为当前时间下的方向;
2、寻宝人的行走规律的转化同样可存储于数组;
3、有关Impossible状态的判断:数据规模不大,我直接使用四维数组标记,依次包含标记寻宝人的位置、宝物的位置和地图的状态(注意不要忘记考虑地图状态)。

代码实现

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stdlib.h>
using namespace std;
#define maxn 35
int maps[maxn][maxn];
int visit[maxn][maxn][maxn][maxn][4];
int dir1[4][2]={{0,1},{0,-1},{1,0},{-1,0}};      //代表地图变化规律E→W→S→N→E
int dir2[4][2]={{0,1},{0,-1},{-1,0},{1,0}};    //寻宝人方向优先规律E→W→N→S
int n,step;   //步数
bool flag,fail;
int tx,ty;  //代表宝藏的位置
int x,y;   //代表寻宝人的位置
int better(int x1,int y1,int x2,int y2)
{
    if((x1-tx)*(x1-tx)+(y1-ty)*(y1-ty)<(x2-tx)*(x2-tx)+(y2-ty)*(y2-ty))
        return 1;
    return 0;
}
//判断是否重复
int judge()
{
    if(visit[x][y][tx][ty][step%4])
    {
        fail=true;
        return 1;
    }
    visit[x][y][tx][ty][step%4]=1;
    return 0;
}
//行走模拟
int succeed()
{
    int sx,sy,dx,dy;
    int t1=(maps[x][y]+step)%4/*寻宝人所在位置的方向*/,t2=(maps[tx][ty]+step)%4/*宝藏所在位置的方向*/;
    if(x==tx&&y==ty) return 1;
    if(judge()) return 0;
    sx=x+dir1[t1][0],sy=y+dir1[t1][1];
    if(!(sx<0||sx>=n||sy<0||sy>=n)) x=sx,y=sy;
    sx=x,sy=y;       //寻宝人第一次走完之后的位置
    for(int i=0;i<4;i++)
    {
        int xxt=x+dir2[i][0],yyt=y+dir2[i][1];
        if(xxt<0||xxt>=n||yyt<0||yyt>=n) continue;
        if(better(xxt,yyt,sx,sy))
        {
            sx=xxt,sy=yyt;
        }
    }
    x=sx,y=sy;    //更新走完之后寻宝人的位置
    dx=tx+dir1[t2][0],dy=ty+dir1[t2][1];
    if(!(dx<0||dx>=n||dy<0||dy>=n))
        tx=dx,ty=dy;
    return 0;
}

int main()
{
    char str[maxn];
    int num=0;
    while(cin>>n)
    {
        if(n==0) break;
        for(int i=0; i<n; i++)
        {
            cin>>str;
            for(int j=0; j<n; j++)
            {
                if(str[j]=='E')
                    maps[i][j]=0;
                else if(str[j]=='W')
                    maps[i][j]=1;
                else if(str[j]=='S')
                    maps[i][j]=2;
                else
                    maps[i][j]=3;
            }
        }
        memset(visit,0,sizeof(visit));
        cout<<"Case "<<++num<<":"<<endl;
        tx=n-1,ty=n-1;
        x=0,y=0;
        step=0,flag=false,fail=false;
        while(step<=99)
        {
            if(succeed())
            {
                cout<<"Get the treasure! At step "<<step<<"."<<endl;
                flag=true;
                break;
            }
            if(fail)
            {
                cout<<"Impossible. At step "<<step<<"."<<endl;
                flag=true;
                break;
            }
            step++;
        }
        if(!flag)
            cout<<"Not sure."<<endl;
        cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值