题目连接:http://soj.sysu.edu.cn/1003
有纸牌游戏 Hit or Miss,游戏流程为:有一套叠好的纸牌(52 张,4 组,值为 1 - 13,花色在本游戏不重要)。 1. 玩家从 1 开始计数; 2. 如果当前计数与最顶端的纸牌数值相同,则扔掉最顶端纸牌,否则将最顶端的纸牌放入这叠纸牌最底部; 3. 计数加一,当计数超过 13 时,回到 1 重新计数。重复第二步;
该游戏也支持多名玩家,最开始只给第一名玩家一叠纸牌(52张)。 1. 玩家从上次自己计数停止处开始计数,最开始为 1; 2. 当玩家接受到纸牌时塞入自己维护的纸牌的最底部。 3. 如果当前计数与自己维护的纸牌最顶端的纸牌数值不同,将最顶端的纸牌放入这叠纸牌最底部,并回到第一步。否则,如果该玩家是最后一名玩家,则扔掉该纸牌,如果不是最后一名玩家,则将该纸牌传递给下一位玩家。数值相同的情况下,游戏都从下一位玩家开始; 4. 当所有牌都被扔了时,游戏胜利。
根据输入的玩家数量以及一套乱序纸牌,判断游戏是否能够胜利。如果能够游戏胜利,则给出结束时,每位玩家或传递或扔掉的最后一张纸牌的数值。否则输出 unwinnable。
题目没有涉及复杂的算法,只要模拟这个游戏就好了……为每个玩家维护一个纸牌队列,然后循环就行。至于游戏是否能够胜利这点,我们只能以循环的次数决定了,当循环次数过大时,游戏结束。(我在提交时设置的次数为 5000,能够 AC)。
代码这块也很朴实。不过我没有用到标准库提供的队列,自己粗暴地实现了一个循环队列来模拟每个玩家维护的纸牌队列~
#include <stdio.h> #include <string.h> #define CARD_MAX 52 #define CARD_CIRCULAR_MAX 53 // 循环队列的大小 #define MAX_TIMES 5000 // 循环队列,多用了一个空位 typedef struct deck { char head; char tail; char cards[CARD_CIRCULAR_MAX]; } deck; int main() { int t, T, i, j, times; int players, removed; scanf("%d", &T); for (t = 1; t <= T; ++t) { removed = 0; scanf("%d", &players); deck cards[players]; for (i = 0; i < players; ++i) { cards[i].head = 0; cards[i].tail = 0; memset(cards[i].cards, 0, sizeof(cards[i].cards)); } // 第一位玩家的初始纸牌 for (i = 0; i < CARD_MAX; ++i) scanf("%d", &(cards[0].cards[i])); cards[0].head = 0; cards[0].tail = i; short last_count[players]; short last_discard[players]; memset(last_count, 0, sizeof(last_count)); memset(last_discard, 0, sizeof(last_discard)); times = 0; // times 判断终止条件 while (times++ < MAX_TIMES && removed != CARD_MAX) { for (i = 0; i < players && removed != CARD_MAX; ++i) { // 玩家没有纸牌(循环队列空的) if (cards[i].tail == cards[i].head) continue; last_count[i] = last_count[i] == 13 ? 1 : last_count[i] + 1; if (cards[i].cards[cards[i].head] == last_count[i]) { // 更新用户丢弃或传递的纸牌 last_discard[i] = cards[i].cards[cards[i].head]; if (i == players - 1) { removed++; } else { // 塞入下一个玩家纸牌底部 cards[i + 1].cards[cards[i + 1].tail] = cards[i].cards[cards[i].head]; cards[i + 1].tail = (cards[i + 1].tail + 1) % CARD_CIRCULAR_MAX; } // 当前玩家丢掉or传递纸牌 cards[i].head = (cards[i].head + 1) % CARD_CIRCULAR_MAX; } else { // 当前玩家把当前纸牌塞入自己纸牌底部 cards[i].cards[cards[i].tail] = cards[i].cards[cards[i].head]; cards[i].head = (cards[i].head + 1) % CARD_CIRCULAR_MAX; cards[i].tail = (cards[i].tail + 1) % CARD_CIRCULAR_MAX; } } } printf("Case %d: ", t); if (removed == CARD_MAX) { printf("%d", last_discard[0]); for (i = 1; i < players; ++i) printf(" %d", last_discard[i]); printf("\n"); } else printf("unwinnable\n"); } }这次稍微用了下 struct!一开始我还用 -> 来取值,但其实是用 . 啦!结构体指针的话才用 -> !
typedef struct a { int q; } a; a t; a* tp; printf("%d, %d, %d", t.q, tp->q, (*tp).q);