传送门UVa 133 - The Dole Queue
链表的题目, 不过好像也可以用队列做.
题意是让N个人排成一个圈, 第一个人从1号逆时针开始数, 第二个人从n号顺时针数, 各自被数到的人就出去, 也就是输出, 如果数到同一个人这个人出去, 直到最后一个.
我的思路是建一个结构体数组, 然后用双向链表操作.
给两个人一人一个计数器, 数到哪个人, 输出那个人的值, 然后改变连结的状态.
需注意:如果第一个人数到了a, 输出后, 下一次本来应该从b开始数, 但是如果b正好是被第二个人数到的, 那么b是要退场的. 因为题目要求是同时退场, 所以实际上应该指从b的下一个人c开始数. 所以这时候就要再前进一个人.
写得有点乱, 而且排名是倒数的... 大家还是不要参考了, 看一下思路就OK. 等以后有时间再改改...
话说我老是说以后以后, 我怎么觉得以后就是无限延期了....
---------------------------------------------------------------------------------------------------------
关于排名的问题, 刚才找了几个其他人的代码, 排名和我也差不多.
可能是因为这题的数据量很小, 看不出差距.
#include
#include
using namespace std;
struct link
{
int value;
link *next, *pre;
};
int main()
{
//freopen("input.txt", "r", stdin);
int N, k, m;
bool first;
int i, j, fcnt, lcnt, cnt;
link *fgo, *lgo;
link peo[30];
while (scanf("%d", &N), N)
{
first = true;
fcnt = lcnt = 1, cnt = 0;
scanf("%d%d", &k, &m);
peo[0].value = 1;
peo[0].pre = &peo[N - 1];
peo[0].next = &peo[1];
for (i = 1; i < N; i++)
{
peo[i].value = i + 1;
peo[i].pre = &peo[i - 1];
peo[i].next = &peo[i + 1];
}
peo[i - 1].next = &peo[0]; //修改最后一个人的指向.
fgo = &peo[0];
lgo = &peo[N - 1];
while (true)
{
while (fcnt < k)
{
fgo = fgo->next;
fcnt++;
}
fcnt = 1;
while (lcnt < m)
{
lgo = lgo->pre;
lcnt++;
}
if (lgo->value == fgo->value)
{
if (first)
printf("%3d", fgo->value);
else
printf(",%3d", fgo->value);
cnt++;
fgo->pre->next = fgo->next;
fgo->next->pre = fgo->pre;
lgo = fgo->pre;
fgo = fgo->next;
}
else
{
if (first)
printf("%3d", fgo->value);
else
printf(",%3d", fgo->value);
cnt++;
fgo->pre->next = fgo->next;
fgo->next->pre = fgo->pre;
fgo = fgo->next;
printf("%3d", lgo->value);
cnt++;
if (lgo->value == fgo->value) //说明fgo指向的这个人即将被消去, 因为是同时消去, 所以应该指向下一个.
fgo = fgo->next;
lgo->pre->next = lgo->next;
lgo->next->pre = lgo->pre;
lgo = lgo->pre;
}
lcnt = 1;
first = false;
if (cnt == N)
{
printf("\n");
break;
}
}
}
return 0;
}