(改)~-7 猴子选大王

7-7 猴子选大王(20 分)
一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?

输入格式:
输入在一行中给一个正整数N(≤1000)。

输出格式:
在一行中输出当选猴王的编号。

输入样例:
11
输出样例:
7

#include
using namespace std;
int a[1005];
void sw(int w, int n){
    for(int i = w; i < n; i++){
        a[i] = a[i+1];
    }
}
int main(){
    int N;
    //int t;
    scanf("%d", &N);
    //t = N;
    for(int i = 1; i <= N; i++){
        a[i] = i;
    }
    for(int i = 3; N>1; i = i+2){
        if(i > N) i=i%N;
        
        if(i == 0) i = N;   //这句一开始没加

        //printf("(%d,%d,%d) " ,N,i, a[i]); 
        sw(i, N);
        N--;
        //printf("%d",)
    }
    printf("%d", a[1]);
    return 0;
}

这题约瑟夫回环我用的是暴力,直接移动整个数组,然而忘了

 for(int i = 3; N>1;      i = i+2    ){
        if(i > N) i=i%N;

这里的i每次加二,那么最后就有可能碰到i=4 , N=2,i%N=0的情况,(因为i每次只加二,及时地取余使得i%N并不会在其他时刻为0)

这是一位学长的代码,通过标记,每次从i1开始判断

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define For(i,l,r) for(int (i)=(int)(l);(i)<(int)(r);++(i))
#define FOR(i,l,r) for(int (i)=(int)(l);(i)<=(int)(r);++(i))
#define rof(i,l,r) for(int (i)=(int)(l);(i)>=(int)(r);--(i))
typedef pair pii;
typedef long long ll;
typedef unsigned long long llu;
typedef unsigned int ui;

const int mxn=1010;
bool vis[mxn];
int main(){
 //   freopen("in.txt","r",stdin);
    int n;scanf("%d",&n);
    int cnt=0,ext=0;
    for(int i=1;i<=n;)if(!vis[i]){
        if(++cnt==3){
            vis[i]=1;++ext;
            cnt=0;

        }
        if(++i>n)i=1;//每次都从1开始 
        if(ext==n-1)break;//剩最后一个 
    }else{
        if(++i>n)i=1;//每次从1开始 
    }

    FOR(i,1,n)if(!vis[i]){
        printf("%d\n",i);
        break;
    }
    return 0;
}

也是暴力的方法,然而通过数组标记,就不需要进行数组的移动

你可能感兴趣的:((改)~-7 猴子选大王)