POJ 1012

这是约瑟夫环的变形,题目大意讲的是共有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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值