7-7 猴子选大王(20 分)
一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
#include<cstdio>
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 <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <set>
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<int,int> 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;
}
也是暴力的方法,然而通过数组标记,就不需要进行数组的移动
网友评论