这是约瑟夫环的变形,题目大意讲的是共有2K个人,前K个是好人,后k个人是坏人,设定一个间距,及当报到什么数是就淘汰,设定间距为m。求出最小的m。
先说一下约瑟夫环吧 ,就是在一串数字中,设定一个间距,假设从0开始报数,报到3的人就要离开,一直循环,直到最后一个。
最开始:0 1 2 3,.......................,n-2,n-1
淘汰的第一人肯定为(m-1)%n 因为从0开始,所以是m-1.不理解的话可以把他们换成具体的数字
淘汰了第一个人之后,剩下的序列为
0 1, 2,3.............m-1,m,............n-2,n-1 因为m-1那个元素被淘汰了 所以不存在了
对应的新元素的位置为
旧:m,....m+1... m+2.....n-2,n-1 0 1...... m-1
新:0,.....1.. .........3...............................................n-2
当n=1时,f(1)=0;只有一个元素,肯定是0号 ,是吧
当n=2时,f(2)=f(1)+3=3,因为当移除某个数之后,值就要重新从0开始报数了,可以自己在草稿纸上写几个数字
但是总共才2个人,f(2)的到的序号是3,显然不可能,所以应该把f(2)得到的序号控制在正确的范围内,所以可以模一个总人数
f(2)=(f(1)+m)%n
当总人数为n时,f(n)=(f(n-1)+m)%n
后面的思路我跟引用程序的作者思路有点不一样,主要是我不太理解为什么要判断那一个条件,就是当再淘汰一个坏人就没有坏人了。就是当淘汰第k+1时。
我的思路效率很低,但是容易理解,这里记录一下,我的想法是给定m,再去判断m是否符合要求呢,如果淘汰的k-1个人中,有 前面k个人中的人,证明该m不可取,因为还没有淘汰坏人就淘汰前面的好人了呀,所以不符合题目要求,是吧。
-----------------------------
代码引用了网友的
#include<stdio.h>
int a[14];int f(int k,int m)
{
int n,i,s;
n=2*k;s=0;
for(i=0;i<k;i++)
{
s=(s+m-1)%(n-i);
if(s<k) return 0;//遇到前k轮中有小于k的直接返回0
}
return 1;
}
int main()
{
int i,k,n;
for(k=1;k<=14;k++)
{
i=k+1;
while(1)
{
if(f(k,i))//t(k+1)的情况
{
a[k]=i;
break;
}
else if(f(k,i+1))//t(k+1)+1的情况
{
a[k]=i+1;
break;
}
i+=k+1;
}
}
while(scanf("%d",&n) && n)
{
printf("%d\n",a[n]);
}
return 0;
}
652

被折叠的 条评论
为什么被折叠?



