约瑟夫环问题(模拟)
链接: link.
时间限制: 1 Sec 内存限制: 128 MB
**
题目描述
**
约瑟夫环问题:设有n(n≤1000)个人围坐一圈,并按顺时针方向1—n编号。从第s个人开始进行报数,报数到第m个人,此人出圈,再从他的下一个人重新开始从1到m的报数进行下去 ,直到只剩一个人为止。
输入
人数n
最先开始报数的那个人的编号s
报到第几个数m
输出
剩下的最后一个人的编号
样例输入
9
1
3
样例输出
1
问题分析(建立模型):
- 用一维数组(Hash[i])表示第i个人是否出圈;
- 用两个变量(j、i)分别存报数人的编号、所报的数;
主要过程(算法):
- 先对标记数组Hash[]初始化;
- j初始化为s,i初始化1,用sum存出圈的人数;
- 当sum 不等于 n - 1 进入循环;
- 每次进循环检测j、i 是否越界,越界重置;
- 当前人如果没有出圈,判断i==m?,若是此人出圈Hash[j] = 1;sum++;
-------------------------------------------------若不是此人报数。跳下一位报数(j++,i++)。
当前人出圈 当前人不报数,跳下一位j++; - 把唯一没有出圈的人找出,打印。
#include <stdio.h>
#include <string.h>
int Hash[1010];
int main() {
int n;
int s;
int m;
scanf("%d%d%d", &n, &s, &m);
memset(Hash, 0, sizeof(Hash));
int sum = 0;
int j = s;
int i = 1;
while(sum != n - 1) {
if(j == n + 1) j = 1;
if(i == m + 1) i = 1;
if(Hash[j] == 0) {
if(i == m) {
Hash[j] = 1;
sum ++;
i++;
j++;
}
else {
j++;
i++;
}
}
else j++;
}
for(int ii =1; ii <= n;ii++) {
if(Hash[ii] == 0) {
printf("%d", ii);
break;
}
}
return 0;
}
/**************************************************************
Problem: 1837
User: 1812190503
Language: C++
Result: 正确
Time:4 ms
Memory:804 kb
****************************************************************/
#include <stdio.h>
int main() {
int n;
int ans;
while(scanf("%d", &n) != EOF && n) {
ans = 1;
for(int i = 2; i <= n; i++) {
ans = (ans + 3) % i;
if(ans == 0) {
ans = i;
}
}
printf("%d\n", ans);
}
return 0;
}
迁移:
#include <stdio.h>
int a[1010];
int main() {
int n;
int s, m;
scanf("%d%d%d", &n, &s, &m);
int j = 1;
int i = s;
int e;
if(s > 1) e = s - 1;
else e = n;
while(i != e) {
if(i == n + 1)
i = 1;
a[j] = i;
j++;
i++;
}
a[j] = e;
int ans = 1;
for(int i = 2; i <= n; i++) {
ans = (ans + m) % i;
if(ans == 0) {
ans = i;
}
}
printf("%d", a[ans]);
return 0;
}