审题:
本题需要我们按照题目中的要求对扑克进行占卜操作,并输出最终的对数思路:
方法一:直接模拟
本题其实就是一个模拟题,但是如果我们按照题意对扑克堆进行操作,就相当于对数组进行数据头插与尾删了,而我们需要进行的次数是较多的,这样会导致效率低下,且模拟也不是很好进行
方法二:递归+虚模拟
由于题目中只有没翻面的扑克需要参与移动,所以每一堆扑克一共可能移动的就只有四张,我们可以创建一个cnt数组负责记录该行还有多少个未翻动扑克,且如果我们的行数组从下标为1开始插入数据,cnt的值就恰好是该行下一个需要移动的扑克牌的下标。
这里我们第一行的扑克牌中四张都没有翻出来过,所以我们需要移动第四张牌,此时我们直接定位到下标为四的牌就是下一个需要移动的牌
那么我们如何模拟本题?
我们发现每次的操作都是一样的,且在抽取到K之前都是逐层进行的,所以我们可以用递归模拟抽牌和放牌的过程。
dfs功能:完成取牌和放牌动作
结合cnt数组后逻辑为:将第x行的最后一张牌抽取出来,对应行的cnt--,继续对抽出来的牌进行dfs
解题:
#include<iostream> using namespace std; const int N = 14; const int n = 14, m = 5; int a[n][m];//存放初始扑克的数组 int cnt[N];//记录每一行未被翻看的扑克数 void dfs(int x) { if (x == 13) return; int num = a[x][cnt[x]]; cnt[x]--; dfs(num); } int main() { //数据录入 for (int i = 1; i <= n - 1; i++) { cnt[i] = 4; for (int j = 1; j <= m - 1; j++) { char c; cin >> c; if (c >= '2' && c <= '9') a[i][j] = c - '0'; else if (c == 'A') a[i][j] = 1; else if (c == '0') a[i][j] = 10; else if (c == 'J') a[i][j] = 11; else if (c == 'Q') a[i][j] = 12; else if (c == 'K') a[i][j] = 13; } } //游戏模拟 for (int i = 1; i <= m - 1; i++) { dfs(a[13][i]); } //统计对数 int answer = 0; for (int i = 1; i <= N - 1; i++) { if (cnt[i] == 0) { answer++; } } cout << answer << endl; return 0; }
1.由于生命牌有四张,所以我们的初始dfs需要进行四次。
2.dfs的结束条件就是抽到死神牌K的时候,直接返回即可
3.最终cnt中若没有未翻转的牌,说明该牌堆含有一对,即cnt[i]值为0时说明第i行含有一对,answer++