玩具谜题 c++

描述

  小南有一套可爱的玩具小人,它们各有不同的职业。
  有一天,这些玩具小人把小南的眼镜藏了起来。小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图:

  这时 singer 告诉小南一个谜題:“眼镜藏在我左数第 3 个玩具小人的右数第 1 个玩具小人的左数第 2 个玩具小人那里。”
  小南发现,这个谜题中玩具小人的朝向非常关键,因为朝内和朝外的玩具小人的左右方向是相反的:面朝圈内的玩具小人,它的左边是顺时针方向,右边是逆时针方向;而面向圈外的玩具小人,它的左边是逆时针方向,右边是顺时针方向。
  小南一边艰难地辨认着玩具小人,一边数着:
  singer 朝内,左数第 3 个是 archer。
  archer 朝外,右数第 1 个是 thinker。
  thinker 朝外,左数第 2 个是 writer。
  所以眼镜藏在 writer 这里!
  虽然成功找回了眼镜,但小南并没有放心。如果下次有更多的玩具小人藏他的眼镜,或是谜題的长度更长,他可能就无法找到眼镜了。所以小南希望你写程序帮他解决类似的谜題。这样的谜題具体可以描述为:
  有 n 个玩具小人围成一圈,已知它们的职业和朝向。现在第 1 个玩具小人告诉小南一个包含 m 条指令的谜題,其中第 i 条指令形如“左数/右数第 si 个玩具小人”。你需要输出依次数完这些指令后,到达的玩具小人的职业。

【子任务】
  子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解决一部分测试数据。
  每个测试点的数据规模及特点如下表:

输入

  输入的第一行包含两个正整数 n,m,表示玩具小人的个数和指令的条数。
  接下来 n 行,每行包含一个整数和一个字符串,以逆时针为顺序给出每个玩具小人的朝向和职业。其中 0 表示朝向圈内,1 表示朝向圈外。保证不会出现其他的数。字符串长度不超过 10 且仅由小写字母构成,字符串不为空,并且字符串两两不同。整数和字符串之间用一个空格隔开。
  接下来 m 行,其中第 i 行包含两个整数 ai,si​,表示第 i 条指令。若 ai=0,表示向左数 si​ 个人;若 ai=1,表示向右数 si​ 个人。 保证 ai​ 不会出现其他的数,1 <= si < n。

输出

  输出一个字符串,表示从第一个读入的小人开始,依次数完 m 条指令后到达的小人的职业。

样例输入

【样例输入1】
7 3
0 singer
0 reader
0 mengbier 
1 thinker
1 archer
0 writer
1 mogician 
0 3
1 1
0 2

【样例输入2】
10 10
1 c
0 r
0 P
1 d
1 e
1 m
1 t
1 y
1 u
0 V
1 7
1 1
1 4
0 5
0 3
0 1
1 6
1 2
0 8
0 4

样例输出

【样例输出1】
writer

【样例输出2】
y

分析

乍一看是一道比较搞的题目,但是看懂以后真不难!

下面提供一下我的理解:

我们把一个小人的面朝方向朝外设为0,朝内设为1,左手方向也设为1,右手为0(好理解一点)。

那么面朝外的小人的左手方向就和面朝内的小人的右手方向是一样的(0+1=1+0),同理面朝内的右手方向和面朝外的左手方向是一样的。(1+0=0+1)。

有了上面的推导,方法就浮现了,我们设定一个数轴,和正方向,正方向增加就加步数,反方向就减步数,值得注意的是,减的时候可能会出现从0走到最后一个位置,因此,我们要加一圈,同理,为了能够从最后一个位置走到第一个位置,要减一圈。

其实说简单点,就是离不开这个:

if(x==a[sum])    sum=(sum-y+m)%m; (01和10的方向是一样的 )
else    sum=(sum+y)%m;            (同上,10和01的方向是一样的 )

其实理解这个就做的出,先自己做做看,做不出再来看代码


代码

我提供两种解法,大家可以做对比,但两种均能AC,本人认为没有太大的好差之分

第一种:(用的上述方法,短小精悍)

#include<stdio.h>
char s[100010][20];
int a[100010];
int main()
{
	int i,j,k,m,n,x,y,sum=0;
	scanf("%d%d",&m,&n);
	for(i=0;i<m;i++)
		scanf("%d%s",&a[i],s[i]);
	for(i=0;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		if(x==a[sum])	sum=(sum-y+m)%m;
		else	sum=(sum+y)%m;
	}
	printf("%s\n",s[sum]);
	return 0;
 } 

第二种:(稍长)

#include <bits/stdc++.h>
#define LL long long 
using namespace std;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e9 + 10;
const int N = 1e6;
struct node{
    int x;
    string s;
}a[N];
LL b,c;
LL n,m;
int main(){
    cin >> n >> m;
    LL now = 0;
    for(LL i = 0;i < n;i ++)
        cin >> a[i].x >> a[i].s;
    for(LL i = 1;i <= m;i ++){
        cin >> b >> c;
        if(a[now].x==0&&b==0||a[now].x==1&&b==1){
            now=(now + n-c)%n;
        }
        else if(a[now].x==0&&b==1||a[now].x==1&&b==0){
            now = (now + c)%n;
        }
    }
    cout << a[now].s << endl;

    system("pause");
    return 0;
}

这应该是我最勤奋的一篇了,老样子,给个赞和关注吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值