Joseph Ring Problem
n people in a circle of sequential numbering, starting from number 1th, press 1, 2, 3 ... order off, report p Exit Circle, the others from 1, 2, 3 start off, newspaper P people again out of the circle, and so on.
Please output the original ordinal number of each exit in the order of exit.
algorithm Idea
recursive by mathematical induction.
Whether you use a linked list or an array, you have one thing in common: to simulate the entire game process, not only is the program more annoying to write, but also the time complexity of O (nm), if NM is very large, can not be calculated in a short time results. We notice that the original question is simply asking for the serial number of the last victor, not the reader simulating the whole process. Therefore, if we want to pursue efficiency, we should break the routine and implement a mathematical strategy.
In order to discuss the convenience, first change the question slightly, does not affect the original intention:
Problem Description: N Individuals (numbered 0~ (n-1)), starting from 0 off, reporting (m-1) exit, the remainder continue to start off from 0. Ask for the winner's number.
We know that the first person (number must be m%n-1) after the column, the remaining n-1 individuals formed a new Joseph Ring (starting with the number of k=m%n):
K k+1 k+2 ... n-2, n-1, 0, 1, 2, ... k-2 and starting from K 0.
Now we're going to do their numbering. Conversion:
K--> 0
K+1--> 1
K+2--> 2
...
...
K-2--> n-2
K-1--> n-1
After the transformation has become completely (n-1) personal count of the child problem, if we know the problem of the solution: for example, X is the ultimate winner, then according to this table to change the x back is not exactly the N personal situation of the solution?!! The formula to change back is very simple, I believe we can be pushed out: X ' = (x+k)%n
How to Know (n-1) the problem of personal count off the solution? Yes, just know (n-2) the individual solution on the line. (n-2) A personal solution? Of course, first of all (n-3)--This is obviously a backward question! Okay, here's the idea, write the recursive formula below:
Make F[i] The number of the person who plays the game M exit the final winner, and the final result is f[n.
Recursive formula
f[1]=0;
f[i]= (f[i-1]+m)%i; (i>1)
Implementation methods
first, the circular chain list
Create a circular chain with n elements, and then iterate and count from the head of the list, if cardinality i = = m, kick out of the element, and continue looping until the current element exits the loop at the same time as the next element
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct LNODE {
int POS;
struct Lnode *next;
} Lnode; /** * Build cyclic link list && loop traversal/void create_ring (Lnode **root, int loc, int n) {Lnode *pre, *current, *n
ew
current = *root;
Pre = NULL;
while (current!= NULL) {pre = current;
Current = current->next;
New = (Lnode *) malloc (sizeof (Lnode));
New->pos = loc;
New->next = current;
if (pre = = NULL) {*root = new;
else {pre->next = new;
////Cyclic link list if (loc = n) {new->next = *root;
}/** * Joseph ring/Void Kickoff_ring (Lnode *head, int p) {int i;
Lnode *pre, *pcur;
Pre = Pcur = head;
while (Pcur->next!= pcur) {for (i = 1; i < P i + +) {pre = Pcur;
Pcur = pcur->next; }
printf ("%d", pcur->pos);
Pre->next = pcur->next;
Free (pcur);
Pcur = pre->next;
printf ("%d\n", Pcur->pos);
Free (pcur);
} void Print_ring (Lnode *head) {Lnode *cur;
cur = head;
while (Cur->next!= head) {printf ("%d", cur->pos);
Cur = cur->next;
printf ("%d\n", Cur->pos);
int main () {int i, p, N;
Lnode *head;
while (scanf ("%d%d", &n, &p)!= EOF) {//Build loop list for (i = 1, head = NULL; I <= n; i + +)
Create_ring (&head, I, N);
Joseph Ring if (P!= 1) kickoff_ring (Head, p);
Else print_ring (head);
return 0;
}
/**************************************************************
problem:1188
User:wangzhengyi
Language:c
result:accepted
TIME:110 ms
memory:912 kb
****************************************************************/
Two, array simulation
the idea is similar to a circular list, less the process of building a circular list
#include <stdio.h> #include <stdlib.h> int main () {int I,
Index, p, N, remain, delete[3001], flag[3001] = {0};
while (scanf ("%d%d", &n, &p)!= EOF) {remain = n;
index = 0;
while (remain >= 1) {for (i = 0; i < n; i + +) {if (flag[i] = 0) {//Count off
Index + +;
P person out of the loop if (index = = p) {//exit out of the loop flag[i] = 1;
Re-numbered index = 0;
Delete[remain-1] = i + 1;
Remain--; The ordinal of each exit is output for (i = n-1 i >= 0; I-) {if (i =
= 0) {printf ("%d\n", Delete[i]);
else {printf ("%d", delete[i]);
}} return 0; }
Third, mathematical deduction
#include <stdio.h>
int main (void)
{
int i, n, M, last;
while (scanf ("%d", &n)!= EOF && n!= 0) {
//Receive datagrams
scanf ("%d", &m);
Joseph Ring Problem
for (i = 2, last = 0; I <= n; i + +) {Last
= (last + m)% i;
}
printf ("%d\n", last + 1);
}
return 0;
}