题意是这样的:
n个人排成一圈,依次编号1~n,从第k个人开始,从1依次往下数,数到m的人出列,
然后又从下一个人从1开始,数到m的人又出列,这样依次进行游戏,直到最后一个人出列。
我想了好几天了没写出来,求大家帮帮忙。
这里我给出了一部分代码:
#include <stdio.h>
#include <stdlib.h>
// 定义一个存储链表的结构体
typedef struct node {
int data;
struct node *next;
} Node;
Node *circle_create(int n);
void count_off(Node *head, int n, int k, int m);
int main() {
int n, k, m;
scanf("%d %d %d", &n, &k, &m);
Node *head = circle_create(n);
count_off(head, n, k, m);
return 0;
}
// 创建循环链表的方法
Node *circle_create(int n) {
Node *temp, *new_node, *head;
int i;
// 创建第一个链表节点并加数据
temp = (Node *) malloc(sizeof(Node));
head = temp;
head->data = 1;
// 创建第 2 到第 n 个链表节点并加数据
for(i = 2; i <= n; i++) {
new_node = (Node *) malloc(sizeof(Node));
new_node->data = i;
temp->next = new_node;
temp = new_node;
}
temp->next = head;
return head;
}
// 现在进行约瑟夫环的算法
void count_off(Node *head, int n, int k, int m) {
}
这是一个数学问题,求解最后只剩一个人时在原队伍排的位置,从1~n计数,查看维基百科有详细的代码解答约瑟夫问题。另外,在微软的hihocoder平台上也有对该问题的小规模、大规模的完全解答,可以注册账号练一下,解答都给出了完整的伪代码:第九十四周 约瑟夫问题。
第一次遇见这个问题会用模拟求解,大一时用数组模拟,用0代表该位置的人被杀掉,非0代表还存活,每次自增为
i = (i + 1) % n
,这样编码比起链表更为简单一点,示例如下:如果要用链表模拟,首先要是个循环链表,而且要实现正确的删除元素。既然要找到最后存活的人,要对链表数目计数,在
count
为1的时候,把最后编号输出。这道问题的详尽解答在第九十四周 约瑟夫问题上有,需要考虑到
n
很大时的情况,n < m
时的情况。至于从k
个人开始点人,与原问题应该等价,求出最终编号后(ans + k) % n
即可。C语言中数组从0
开始,输出答案要注意一下。希望对你有所帮助。