问题描述 :
圆桌上围坐着2n个人。其中n个人是好人,另外n个人是坏人。如果从第一个人开始数数,数到第m个人,则立即处死该人;然后从被处死的人之后开始数数,再将数到的第m个人处死……依此方法不断处死围坐在圆桌上的人。试问预先应如何安排这些好人与坏人的座位,能使得在处死n个人之后,圆桌上围坐的剩余的n个人全是好人。
输入说明 :
输入:好人和坏人的人数n(<=32767)、步长m(<=50);
输出说明 :
输出2n个大写字母,‘G’表示好人,‘B’表示坏人,50个字母为一行。
输入范例 :
52 6
输出范例 :
BGGBGBGGBBBBGGGGBBBGBGGBGBBGGBBGBGBBGGGBBBGBGGBBGG
BBGBBGGGGBBBBGGBGGBBGBBGGBGBBGGBBBGGBGGBBGGGBBGBGG
GBGB
#include<iostream>
using namespace std;
struct ListNode {
char data;
int flag; //好人为1,坏人为-1
ListNode *next;
};
ListNode *createByArray(char a[],int n) {
ListNode *head,*r,*p; //r指向尾节点
head = new ListNode;
head->next = NULL;
r = head;
for(int i = 0; i < n; i++) {
p = new ListNode;
p->data = a[i];
p->flag = 1; //初始都为好人
r->next = p;
r = p;
}
r->next = head; //尾指针指向头节点,构成循环链表
return head;
}
void display(ListNode *head) {
ListNode *p;
p = head->next;
int i = 0;
while(p != head) {
if(p->flag == 1) {
cout<<"G";
}
else {
cout<<"B";
}
i++;
if(i % 50 == 0) {
cout<<endl;
}
p = p->next;
}
}
/*
步长m,坏人人数为n
每次遍历到步长时,如果当前节点不是坏人置当前这个结点的flag为-1,让它变成坏人,重置cnt,坏人人数减1,如果当前这个节点已经是坏人,则跳过这个节点
没有遍历到步长时,如果当前节点不是坏人,则cnt++,接着遍历下个节点
遍历到头节点也要跳过
*/
void josephus(ListNode *head,int m,int n) {
ListNode *cur = head->next;
int cnt = 1;
while(n > 0) {
if(cnt == m) {
if(cur->flag == 1) {
cur->flag = -1;
cnt = 1;
n--;
cur = cur->next;
}
else {
cur = cur->next;
}
}
else if(cnt < m) {
if(cur->flag = -1) {
cnt++;
cur = cur->next;
}
else {
cur = cur->next;
}
}
//跳过头节点
if(cur == head) {
cur = cur->next;
}
}
}
int main(void)
{
int n,m;
cin>>n;
cin>>m;
char arr[2*n];
for(int i = 0; i < 2*n; i++)
{
arr[i] = 'G';
}
ListNode *head;
head = createByArray(arr,2*n);
josephus(head,m,n);
display(head);
return 0;
}