1
Joseph Problem(35分)
题目内容:
實作Joseph problem.
假設一開始有N個人,編號1~N,
按照順序以順時針圍成一個圓圈。
遊戲開始時,編號1的人拿刀。
之後每一輪刀子會被往下傳M個人,
而當輪最後拿到刀子的人會將他的下一個人殺掉,
殺完後刀子會再傳給被殺的下一個人。
這樣一輪就算結束。
遊戲會進行許多輪,直到只剩下最後一個人。
範例1:N=5, M=2
第一輪:刀子傳給3號,4號被殺,刀子再傳給5號 (1 2 3 5)
第二輪:刀子傳給2號,3號被殺,刀子再傳給5號 (1 2 5)
第三輪:刀子傳給2號,5號被殺,刀子再傳給1號 (1 2)
第四輪:刀子傳給1號,2號被殺,最後1號存活。
範例2:N=4, M=3
第一輪:刀子傳給4號,1號被殺,刀子再傳給2號 (2 3 4)
第二輪:刀子傳給2號,3號被殺,刀子再傳給4號 (2 4)
第三輪:刀子傳給2號,4號被殺,最後2號存活。
输入格式:
輸入第一行為一個數字T,代表測資的筆數。
接下來會有T筆測資,每一筆測資一行,
會有兩個數字N,M,數字間以空格區隔。
數字範圍:
T < 1000
0 < N <= 1000
0 < M <= 1000
输出格式:
輸出一行數字,將每筆測資最後存活下來的人的編號加總。
输入样例:
3
5 2
4 3
8 4
输出样例:
4
#include <stdio.h>
#include <stdlib.h>
#define ERROR NULL
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
Position Find(List L, ElementType X);
List Insert(List L, ElementType X, Position P);
List Delete(List L, Position P);
int main()
{
int N, n, m;
int ans = 0;
scanf_s("%d", &N);
while (N--)
{
List L;
L = NULL;
scanf_s("%d %d", &n, &m);
for (int i = n; i >=1; i--)
{
L = Insert(L, i, L);
}
PtrToLNode p, q, temp;
p = L;
while (p->Next)
{
//printf("%d ", p->Data);
p = p->Next;
}
p->Next = L;
q = L;
while (q->Next != q)
{
for (int i = 1; i <=m; i++)
{
q = q->Next;
}
temp = q->Next;
q->Next = temp->Next;
free(temp);
q = q->Next;
}
ans += q->Data;
//printf("%d\n", q->Data);
}
printf("%d\n", ans);
}
List Insert(List L, ElementType X, Position P)
{
PtrToLNode Current;
PtrToLNode p = (PtrToLNode)malloc(sizeof(struct LNode));
if (P == L) // 如果要插入的元素就是头节点
{
p->Data = X;
p->Next = L;
L = p;
return L;
}
Current = L;
while (Current&&Current->Next != P)
{
Current = Current->Next;
}
if (Current == NULL)
{
printf("Wrong Position for Insertion\n");
return ERROR;
}
p->Data = X;
p->Next = Current->Next;
Current->Next = p;
return L;
}
Position Find(List L, ElementType X)
{
PtrToLNode p = L;
while (p)
{
if (p->Data == X)
return p;
p = p->Next;
}
return ERROR;
}
List Delete(List L, Position P)
{
PtrToLNode p = L;
PtrToLNode temp;
if (p == P) // 如果删除的是头节点
{
L = L->Next;
free(p);
return L;
}
while (p&&p->Next != P)
{
p = p->Next;
}
if (p == NULL) // 如果找不到要删除的节点
{
printf("Wrong Position for Deletion\n");
return ERROR;
}
temp = p->Next;
p->Next = temp->Next;
free(temp);
return L;
}