poj 1012 应用枚举的方法

#include <stdio.h>

int main()

    int k;
    int a[15]={0};//a[k]存储最小的m(0<k<14)
    while(1)
    {
        scanf("%d",&k);
        if(k==0)break;   
        if(a[k]==0)  //如果未计算过,使用枚举法找最小的m,主要考虑到测试数据中可能有重复的k,否则可能会超时
        {
            int m=k+1;   //初始化m,被杀的一定大于k
            int n=2*k;   //共有n个guys(1~n形成一个环)
            while(1)
            {         
                int pre=n,delc=0;//delc存储已杀的数目
                int mm=n;//mm为剩余的人数
                int p=1;//pre是p的前驱位置
                while(delc<k)
                {
                   int nn = m%mm;
                   p=(pre+nn)%mm;//p为被杀的人的位置,当p值大于k时杀的人是bad guy
                   if(p==0) p = mm;
                   if(p>k)//杀一个bad guy
                   {
                       mm--;
                       pre=p-1;
                       delc++;
                   }    
                   else break;       
                }
                if(delc == k) break;  //已经杀了k个bad guys,找到了问题的解
                m++;                  //枚举下一个m
                if(m%n==1) m = m+k;   //因为第一个被杀的人一定是编号大于k的人
            }  
            a[k]=m;  //存储结果
        }      
        printf("%d\n",a[k]);
    }    
    
    return 0;

}   


在poj 上AC了,344MS。之后看了网上的数学推导,感觉数学的方法还是不太好想,个人认为我这个好理解一些,时间上可能不是很快!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值