算法竞赛进阶指南-30.占卜DIY
题目链接
达达学会了使用扑克 DIY 占卜。
方法如下:
一副去掉大小王的扑克共 张,打乱后均分为 堆,编号 ,每堆 张,其中第 堆称作“生命牌”,也就是说你有 条命。
这里边,$ 4 $ 张 $ K $ 被称作死神。
初始状态下,所有的牌背面朝上扣下。
流程如下:
1.抽取生命牌中的最上面一张(第一张)。
2.把这张牌翻开,正面朝上,放到牌上的数字所对应编号的堆的最上边。(例如抽到 $ 2 $,正面朝上放到第 $ 2 $ 堆牌最上面,又比如抽到 $ J $,放到第 $ 11 $ 堆牌最上边,注意是正面朝上放)
3.从刚放了牌的那一堆最底下(最后一张)抽取一张牌,重复第 $ 2 $ 步。(例如你上次抽了 $ 2 $,放到了第二堆顶部,现在抽第二堆最后一张发现是 $ 8 $,又放到第 $ 8 $ 堆顶部…)
4.在抽牌过程中如果抽到 $ K $,则称死了一条命,就扔掉 $ K $ 再从第 $ 1 $ 步开始。
5.当发现四条命都死了以后,统计现在每堆牌上边正面朝上的牌的数目,只要同一数字的牌出现 $ 4 $ 张正面朝上的牌(比如 $ 4 $ 个 $ A $),则称“开了一对”,当然 $ 4 $ 个 $ K $ 是不算的。
6.统计一共开了多少对,开了 $ 0 $ 对称作”极凶”,$ 1 \sim 2 $ 对为“大凶”,$ 3 $ 对为“凶”,$ 4 \sim 5 $ 对为“小凶”,$ 6 $ 对为“中庸”,$ 7 \sim 8 $ 对“小吉”,$ 9 $ 对为“吉”,$ 10 \sim 11 $ 为“大吉”,$ 12 $ 为“满堂开花,极吉”。
输入格式
一共输入 $ 13 $ 行数据,每行四个数字或字母,表示每堆牌的具体牌型(不区分花色只区分数字),每堆输入的顺序为从上到下。
为了便于读入,用 $ 0 $ 代表 $ 10 $。
同行数字用空格隔开。
输出格式
输出一个整数,代表统计得到的开出的总对数。
输入样例:
8 5 A A
K 5 3 2
9 6 0 6
3 4 3 4
3 4 4 5
5 6 7 6
8 7 7 7
9 9 8 8
9 0 0 0
K J J J
Q A Q K
J Q 2 2
A K Q 2
输出样例:
9
Method : 模拟
理解了题意就很好做的一道模拟题。
这里使用的是数组 + 额外的两个idx模拟的抽取卡牌的过程,也可以使用双端队列来模拟抽取卡牌的过程。
吐槽: memset是真的难用,有时候会莫名其妙初始化不了
#include <vector>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 13 + 7;
const int M = 4 + 7;
char poke[N][M];
vector<int> idx_top(N, 1); // 从上往下抽到第i张牌
vector<int> idx_bot(N, 4); // 从下往上抽到第i张牌
int cnt[N]; // 第i堆正面朝上的纸牌数
int life = 4;
int trans(char c) {
switch(c) {
case '0' :
return 10;
case 'J' :
return 11;
case 'Q' :
return 12;
case 'K' :
return 13;
case 'A' :
return 1;
default :
return c - '0';
}
}
int pick_top(int cur) {
int pick = trans(poke[cur][idx_top[cur]]);
idx_top[cur] ++;
cnt[pick] ++;
if (pick == 13) life --;
return pick;
}
int pick_bot(int cur) {
int pick = trans(poke[cur][idx_bot[cur]]);
idx_bot[cur] --;
cnt[pick] ++;
if (pick == 13) life --;
return pick;
}
int main() {
memset(poke, '0', sizeof poke);
memset(cnt, 0, sizeof cnt);
for (int i = 1; i <= 13; i ++) {
for (int j = 1; j <= 4; j ++) {
// scanf("%c", &poke[i][j]);
cin >> poke[i][j];
}
}
int cur = 13;
while (life != 0) {
if (cur == 13) cur = pick_top(cur);
else cur = (pick_bot(cur));
}
int res = 0;
for (int i = 1; i <= 12; i ++) {
if (cnt[i] == 4) {
res ++;
}
}
cout << res << endl;
return 0;
}
复杂度分析
时间复杂度:, 其中为13,为4。
空间复杂度:, 其中为13,为4。
本博客所有文章均采用 CC BY-NC-SA 4.0 协议 ,禁止商用,转载请注明出处!