原文链接: POJ 3750 约瑟夫环
上一篇: python 字符串 处理
下一篇: TensorFlow 简单使用
Description
有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。
Input
第一行输入小孩的人数N(N<=64)
接下来每行输入一个小孩的名字(人名不超过15个字符)
最后一行输入W,S (W < N),用逗号","间隔
Output
按人名输出小孩按顺序出列的顺序,每行输出一个人名
Sample Input
5 Xiaoming Xiaohua Xiaowang Zhangsan Lisi 2,3
Sample Output
Zhangsan Xiaohua Xiaoming Xiaowang Lisi
解题思路:用一个数组存下小孩的名字,然后再开辟一个标记数组。模拟题目中说的从w开始往下找,找到第s个的时候标记数组置1。每次查找时检测当前小孩是否已经出局。如果出局就跳过。
简单数组模拟
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
int const MAX = 1e6 + 1;
int const INF = 1 << 30;
double const EPS = 0.00000001;
using namespace std;
int a[100];
char name[70][25];
int main(){
int n, w, s;
scanf("%d", &n);
for (int i = 0; i < n; i++){
a[i] = i;
scanf("%s", name[i]);
}
scanf("%d,%d", &w, &s);
int step = 1, p = w - 1, cnt = n;
while (n){
//每次进入循环,说明标号为p的人报的数是step
if (step % s == 0){
printf("%s\n", name[p]);
a[p] = -1;
n--;
step = 1;
//找下一个有效的报数人,注意可能到这一步时n为0
while (a[p] == -1 && n)
p = (p + 1) % cnt;
continue;
}
//模拟报数,如果p有效,报数加一
p = (p + 1) % cnt;
if (a[p] != -1)
step++;
}
return 0;
}
链表模拟,速度比数组快
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#define LL long long
int const MAX = 1e6 + 1;
int const INF = 1 << 30;
double const EPS = 0.00000001;
using namespace std;
struct Node {
int data;
Node* next;
Node(int d = 0, Node* next = NULL) : data(d), next(next){};
};
using namespace std;
int n, w, s;
char name[70][25];
int main(){
scanf("%d", &n);
//头结点
Node* head = new Node();
for (int i = 0; i < n; i++){
scanf("%s", name[i]);
}
scanf("%d,%d", &w, &s);
//构造链表
Node* tp = head;
for (int i = 0; i < n; i++){
Node* nd = new Node(i);
tp->next = nd;
tp = tp->next;
}
tp->next = head->next;
// while (tp->next){
// printf("%d ", tp->next->data);
// tp = tp->next;
// }
tp = head;
Node* p;
//找到初始位置
while (w--){
p = tp;
tp = tp->next;
}
while (n--){
//找到需要删除的上一个节点
for (int i = 1; i < s; i++){
p = tp;
tp = tp->next;
}
if (tp == p){
printf("%s\n", name[tp->data]);
} else {
printf("%s\n", name[tp->data]);
p->next = tp->next;
tp = tp->next;
}
}
return 0;
}
直接模拟起始w=(w+n-1)%n,出去下标w=(w+s-1)%n,在后面要把环的下标更新即可。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int main(){
int i, j, w, s, n;
char a[65][16];
int p[65];
scanf("%d", &n);
for (i = 0; i < n; i++){
p[i] = i;
scanf("%s", &a[i]);
}
scanf("%d,%d", &w, &s);
w = (w + n - 1) % n;
while (n){
w = (w + s - 1) % n;
printf("%s\n", a[p[w]]);
for (j = w; j < n - 1; j++)
p[j] = p[j + 1];
n--;
}
return 0;
}