1234: 華科版C語言程式設計教程(第二版)習題6.11(約瑟夫問題)

haixinjiazu發表於2019-05-10

題目:
Description
n個人圍成一圈,依次從1至n編號。從編號為1的人開始1至k報數,凡報數為k的人退出圈子,輸出最後留下的一個人原來的編號。
Input
 首先輸入一個t,表示有t組資料(1<= t <= 10010)
然後有t行,每行有2個正整數n和k。(1<= n,k<= 20)
Output
 對於每組測試資料,輸出一個數,表示最後留下來的人的編號。

樣例:
Sample Input
3
10 3
7 1
5 4
Sample Output
4
7
1

提示: 例如第三組樣例:5個人圍成一圈,編號1-5。第一輪報數4號出列,第二輪從5開始報數1,3報4,3出列,第三輪從5開始報1,5報4,5出列,第四輪1開始報1,2報4,2出列,最後剩下的為1號。

思路:這題是一個約瑟夫問題,處理方式就是用一個陣列,其下標表示序號,其存的指用0,1分別表示其是否出去了,然後用迴圈,依次進行,若沒出去則看這個是第幾個沒出去的,若是要出去的報數的那個數的倍數,則讓其出去,即將存的指由1變為0;然後再找一個計數器表示剩餘人數,當剩餘只有1個的時候則跳出迴圈,輸出最後的;

新技巧:在於用陣列的下標表示序號,用內部存的值表示其狀態,還有一個重要的點就是人數計數器,因為這裡是要記錄出去的人數,所以一開始計數器為總數,之後每次出去就減一,這樣從邏輯上好記錄與理解;

程式碼:

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

int main()
{
    int i,t,x,y,a[10015];
    scanf("%d",&t);
    for(i=0;i<t;i++)
    {
        memset(a,0,sizeof(a));
        scanf("%d%d",&x,&y);
        int num=x,j,k;
        for(j=1;j<=x;j++)
            a[j]=1;
        k=0;
        for(j=0;;j++)
        {

            if(a[j%x+1])
            {
                k++;
                if(k%y==0)
                {
                    if(num==1)
                        break;
                    a[j%x+1]=0;
                    num--;
                }
            }
        }
        printf("%d
",j%x+1);
    }
    return 0;
}

相關文章