关于约瑟夫环的改编问题是这样的:假设有 N 个人,围成一圈,然后给你一个数 M ,围成一圈的人当中一个从 1 开始数,然后数到 M 退出,接下来剩下来的人继续从 1 开始继续数, 直到剩下最后一个人,求剩下这个人刚开始的位置。
刚开始学习 C语言的时候接触这个问题,对于不爱动脑的我,是非常难的,所以我去向学长请教,然后学长跟我说了 “环形数组”,真是醍醐灌顶 (hhhh...)然后我就抱着试一试的心态去写代码了,刚开始的代码如下:
#include
int arry[1010], sum = 0, N, M;
int main()
{
scanf("%d %d",&N, &M);
for(int i=1,cnt=0;i<=N;i++)
{
if(arry[i]==0 && sum < N - 1)
{
cnt++;
if(cnt==M)
{
arry[i]++;
sum++;
cnt=0;
}
}
if(i == N) i=0;
if(sum == N-1) break;
}
for(int i=1;i<=N;i++)
{
if(arry[i]==0) printf("%d\n",i);
}
return 0;
}
思路也比较简单,就是刚开始把每个数组上面的数全部置 0 ,数到的就自增 1 就认为退出了,然后不断进行遍历到 N - 1 个数就行了。
当然这篇文章并不是讲 C 语言的, 其当中的思想就是一个环形数组,对于环形数组来说,在 C++ 的 STL 里面有一个数据结构 "queue".这个数据结构叫做栈,因为和环形数组很像,所以就想到这个问题,先上代码:
#include
#include
using namespace std;
int n, m, temp;
queue lis;
int main()
{
cin >> n >> m;
for(int i = 1; i <= n ; i++)
{
lis.push(i);
}
int cnt = 1;
while(!lis.empty())
{
temp = lis.front();
lis.pop();
if(cnt == m)
{
cnt = 0;
}
else
{
lis.push(temp);
}
cnt++;
}
cout << temp<
这样就不用那么复杂了,这就相当于一个队伍,数到不是 M 的就从队首离开,然后到队尾继续排队。
文章如有错误,请dalao批评改正。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)