約瑟夫環總結
阿新 • • 發佈:2020-08-19
約瑟夫環
約瑟夫環算是比較經典的題目,我的解法是採用陣列模擬連結串列
通過例題來分析吧
洛谷P1996約瑟夫問題
AC程式碼
#include<stdio.h> int pre[101],nxt[101]; int main(){ int m,n; scanf("%d %d",&n,&m); int i,j,k; for (i=1;i<=n;i++){ pre[i]=i-1;//存放當前點的上一點 nxt[i]=i+1;//存放當前點的下一點 } pre[1]=n;nxt[n]=1;//讓最後一點的下一點是第一點,第一點的上一點是最後一點,形成迴圈 int now=n;//這樣才能使在等一下的迴圈一開始now=1;見這行下面的第四行,保證第一次now=nxt[now]後now==1 int l,r; for (i=1;i<=n;i++){ for (j=1;j<=m;j++){ now=nxt[now]; } printf("%d ",now); l=pre[now];r=nxt[now]; nxt[l]=r;pre[r]=l; //將now這個點去掉,讓nxt[now]成為pre[now]的下一點,pre[now]成為nxt[now]的上一點,有點拗口,可以看下面的一張圖(有點醜哈哈) } return 0; }
2 出色的物理引擎 (100分)
卡羅拉最近沉迷於ark遊戲,遊戲中的地圖上有n個浮空的石頭圍成了一圈,在優秀的物理引擎支援下,這些石頭會自動落下。她發現石頭落下的順序是有規律的。一共有n個石頭,從第一塊石頭開始數,數到第m個石頭,那塊就是第一個落下的石頭;之後從第一個落下的石頭後一個重新從1開始數,同樣數到第m個石頭,那個就是第二個落下的石頭;以此類推。為了方便,對這些石頭從1開始編號。卡羅拉現在想知道最後落下的是那一塊石頭?
輸入格式:
輸入包含兩個整數n和m (1<=m,n<=1000)。
輸出格式:
輸出一 個整數,代表最後落下的石頭的編號。
輸入樣例:
10 3
輸出樣例:
4
這題的處理方法和上面基本一模一樣,只有在輸出時不同,如果理解了上面那一題,可以拿這題練練手,就不再繼續解釋了(不好意思哈有點懶
AC程式碼
#include<string.h> #include<stdio.h> #include<stdlib.h> int pre[10007],nxt[10007]; int main() { int i,j,k,l,r,m,n; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ pre[i]=i-1,nxt[i]=i+1; } nxt[n]=1,pre[1]=n; k=n; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ k=nxt[k]; } if (i==n) { printf("%d",k); break; } l=pre[k],r=nxt[k]; pre[r]=l,nxt[l]=r; } return 0; }
#include<stdio.h>
int main(){
int k,n;
scanf("%d",&k);
int m=k;
int i,j,temp=1;
while(temp){
//假設序號為0~k-1都是好人,k~2*k-1都是壞人
m++;// m至少要大於1
int bekilled=0;//第一個被殺的序號
for (i=0;i<k;i++){
//按照假設,序號為0~k-1都是好人,k~2*k-1都是壞人
bekilled=(bekilled+m-1)%(2*k-i);//下一個被殺的序號
if (bekilled<k){//如果被殺者序號小於k,則好人被殺,不符合題意
break;
}
if (i==k-1){//當被殺者(前面的程式碼保證了被殺的都是壞人)達到 k人,達到題設要求
temp=0;
}
}
}
printf("%d",m);
return 0;
}