POJ 3750 约瑟夫环

原文链接: 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;
}

链表模拟,速度比数组快

213520_DpQ9_2856757.png

#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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值