• poj1012


    Joseph
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 52097   Accepted: 19838

    Description

    The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved. 

    Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy. 

    Input

    The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.

    Output

    The output file will consist of separate lines containing m corresponding to k in the input file.

    Sample Input

    3
    4
    0
    

    Sample Output

    5
    30
    
    

    Source

    大致题意:

    有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k)

    现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去。

    问当m为什么值时,可以使得在出现好人死亡之前,k个坏人先全部死掉?

    PS:当前一轮第m个人死去后,下一轮的编号为1的人 为 前一轮编号为m+1的人

       前一轮恰好是最后一个人死掉,则下一轮循环回到开头那个人报“1”

    解题思路:

    经典的约瑟夫水题

    由于k值比较少(1~13),暴力枚举m就可以了

    递推公式为:

    ans[i];  //第i轮杀掉 对应当前轮的编号为ans[i]的人

    ans[0]=0;

    ans[i]=(ans[i-1]+m-1)%(n-i+1);   (i>1  ,  总人数n=2k 则n-i为第i轮剩余的人数)

    正规代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int a[30],ans[30];//第i轮杀掉 对应当前轮的编号为ans[i]的人
    int main(){
        int n,k,m;
        while(scanf("%d",&k)==1&&k){
            if(a[k]) {printf("%d
    ",a[k]);continue;}//方便重复询问(数据范围太小) 
            m=1;//所求的最少的报数
            n=2*k;//总人数
            for(int i=1;i<=k;i++){
                ans[i]=(ans[i-1]+m-1)%(n-i+1);//n-i为剩余的人数,+1从下一个人开始 
                if(ans[i]<k){//ans[i]=>[0..k) 把好人杀掉了,m值不是所求
                    i=0;
                    m++;//枚举m值
                }
            }
            a[k]=m;
            printf("%d
    ",m);
        }    
        return 0;
    }

    打表写法

    #include<cstdio>
    int k,a[17]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881,1245064};
    int main(){
        while(scanf("%d",&k)==1&&k)
            printf("%d
    ",a[k]);
        return 0;
    }
  • 相关阅读:
    异常问题处理记录(转载篇)
    linux服务器出现大量连接:sshd: root@notty
    第4章 Python运算符
    第2章 python基础知识
    第1章 python环境搭建
    Tomcat漏洞升级
    第3章 数据类型、运算符和表达式
    第2章 C语言基础知识
    第1章 概述
    第1章 企业管理概论
  • 原文地址:https://www.cnblogs.com/shenben/p/5516149.html
Copyright © 2020-2023  润新知