且未

博客园 首页 新随笔 联系 订阅 管理

题目

题意:一共有2k个人,分别为k个好人和k个坏人,现在我们需要每隔m个人把坏人挑出来,但是条件是最后一个坏人挑出来前不能有好人被挑出来。。问最小的m是多少

约瑟夫环问题,通常解决这类问题时我们把编号设为从0~n-1。

求出每一轮出列的人:start = (start + m - 1) % n

模拟过程如下(以六个人,第五为例):

1 2 3 4 5 6 易发现start1 = (0 + 5 - 1)% 6 = 4, 即a[4] = 5这个人出列

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

int k,a[15];
bool IsGood(int k, int x){
    int start = 0, n = k*2;
    while(n > k){
        start = (start + x - 1) % n;
        if(start < k)   return false;//要kill的这个人是否 < k
        else    n--;
    }
    return true;
}

void init(){
    for(int k=1; k<=13; k++)
            for(int hoop=1; ; hoop++)
                if(IsGood(k,hoop)) {a[k] = hoop; break;}
}

int main(){
    init();
    while(scanf("%d",&k) == 1){
        if(k == 0)  break;
        printf("%d\n",a[k]);
    }
    return 0;
}

原始约瑟夫环问题代码:

/* 约瑟夫环问题 */
# include <stdio.h>
int main()
{
    int m, n, i, s;
 
    while (~scanf("%d%d", &n, &m))//n个人,kill m
    {
        s = 0;          
        for (i = 2; i <= n; ++i)
            s = (s + m) % i;
        printf("%d\n", s+1);       // 原问题的编号是从1开始的
    }
 
    return 0;
}

 

posted on 2018-09-17 15:04  阿聊  阅读(166)  评论(0编辑  收藏  举报