一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
code:(约瑟夫环问题)
方式一:
#include <stdio.h>
int main()
{
int i, n, cnt1 = 0, cnt2 = 0;
scanf("%d", &n);
int a[n];
for (i = 0; i < n; i++){
a[i] = 0;
}
i = 0;
while (1){
if (a[i] != -1){
cnt1++;
}
if (cnt1 == 3){
a[i] = -1;
cnt1 = 0;
cnt2++;
}
if (cnt2 == n){
printf("%d\n", i + 1);
break;
}
i == n - 1 ? i = 0 : i++;
}
return 0;
}
设一个数组a[i],两个计数器cnt1,cnt2。a[i]从第一个数往后数,cnt1负责从1计到3,每数到3,将数组项记为“-1”,同时只有数组项不为“-1”时,cnt1才可加一。cnt2负责数有几个猴子退出(每当cnt1满3了加1)。当cnt2计到最后一个n时,看此时是第几个猴子(i+1)。
方式二:(递归算法)
#include<stdio.h>
int f(int);
int main(){
int n;
scanf("%d",&n);
printf("%d\n",f(n));
return 0;
}
int f(int n){
int ret;
if(n==1) ret=1;
if(n==2) ret=2;
if(n>=3){
f(n-1)<=(n-3) ? (ret=(f(n-1)+3)): (ret=f(n-1)-(n-3));
}
return ret;
}
f(1)={1}=1
f(2)={1,2}=2
f(3)={1,2,3} <第一次去掉3,变成> {1,2} <根据f(2)选第2个> 2
f(4)={1,2,3,4} <去3,从4排序> {4,1,2} <第2个> 2
f(n)={1,2,3,……,n} <去3,从4排序> {4,5,6,……,n,1,2} <选第f(n-1)个>
注意(?:)语句,?比 = 的优先级高,所以?后的表达式要加括号,不然左值非变量,报错。