1. 程式人生 > >hdu 1443 Joseph【約瑟夫環】

hdu 1443 Joseph【約瑟夫環】

題目

題意:一共有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", &m, &n))
    {
        s = 0;          
        for (i = 2; i <= n; ++i)
            s = (s + m) % i;
        printf("%d\n", s+1);       // 原問題的編號是從1開始的
    }
 
    return 0;
}