一个小游戏--1051--2023/1/5

这篇文章讨论了一种编程问题的两种解题思路,涉及顺时针和逆时针移动元素的算法。通过标记和填充空位的方法,解决了一个关于循环移动元素的挑战。代码示例展示了如何实现这两种方法,最终找出特定条件下的最后一个元素。
摘要由CSDN通过智能技术生成

这个题目呢其实有两种思路。

第一种:就是可以给每一次找到的点打上标志,然后最后一个没有打上标志的就是最后一个点。

第二种:就是每一次退出一个我就将后面的数填充到那个空位置上,然后留下最后一个点就是答案。

第一种方法呢,就是需要一步一步地动,每动一步都需要判断这个点是否标志过。比较暴力。

第二种方法,可以直接计算,因为填补了空位置就可以直接用+(m-1)或者-(m-1)来运动,就会比较方便。

但是不管是第一种还是第二种都需要每次判断下标是否是合理的,并且做出相应的处理,就是不能出现负数和超过最大的下标的情况。

好啦,给个位官爷上代码喽:(代码中有很多注释,以方便理解)

#include <stdio.h>
#include <math.h>
#include <string.h>

//这个题目就是根据题意模拟
//这个题目呢有两个方向,一个是顺时针,一个是逆时针,而且每一个开始的位置都是这个这次时针的下一个
//每一次退出一个我就将后面的数填充到那个空位置上

int main(){
	int k;
	scanf("%d",&k);
	while(k--){
		int n,m;
		scanf("%d%d",&n,&m);
		int ans[n];
		//初始化每个位置上人的序号
		for(int i=0;i<n;i++) ans[i]=i+1;
		int cnt=n-1,sta=0;
		m--;//因为第一个点也算所以要减一。
		while(cnt){//需要剩下一个人,因此需要循环n-1遍
			sta=(sta+m)%n;//顺时针移动
			cnt--;
			for(int j=sta;j<n-1;j++) ans[j]=ans[j+1];//填充这个空位置,因为将后面的填充了这个空位,顺时针的时候也就相当于不用向后移动一个位置了
			n--;//总人数减1
			if(!cnt) break;//注意判断cnt是否为0
			int ret=(sta-m);//逆时针移动
			//abs()函数是取绝对值
			sta=(ret+(abs(ret)/n+1)*n)%n;//减出来会有负数这一步操作就是将负数转换为正数
			//具体分析一下这一步
			//首先如果ret>0,那么(ret+(abs(ret)/n+1)*n)%n=ret%n;
			//如果ret<0,那么我要让ret变成正数,首先我肯定要计算出ret比n大了多少,所以用abs(ret)/n表示abs(ret)是n的多少倍
			//由于这个除法是向下取整的,因此我要增加一倍,也就是(abs(ret)/n+1)*n
			//然后最终结果取余n就好
			cnt--;
			for(int j=sta;j<n-1;j++) ans[j]=ans[j+1];//填充这个空位置,注意这一步是顺时针填充,因为逆时针填充很麻烦,因此sta要逆时针走一步
			n--;//总人数减一
			sta=(sta-1+n)%n;//因为逆时针是反向移动的,但是我填充是正向填充的,所以不一样
		}
		printf("%d\n",ans[0]);//输出最后一个人
	}
	return 0;
}

继续加油哦,我们明天再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值