算法题(166):占卜DIY
审题:
本题需要我们按照题目中的要求对扑克进行占卜操作,并输出最终的对数思路:
方法一:直接模拟
本题其实就是一个模拟题,但是如果我们按照题意对扑克堆进行操作,就相当于对数组进行数据头插与尾删了,而我们需要进行的次数是较多的,这样会导致效率低下,且模拟也不是很好进行
方法二:递归+虚模拟
由于题目中只有没翻面的扑克需要参与移动,所以每一堆扑克一共可能移动的就只有四张,我们可以创建一个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++
P10457 占卜DIY - 洛谷