这个也只麻烦一点点而已,与easy version不同的地方在于允许3张连续的牌出现
进行这种判断只需要进行一遍DFS就行了
关键在于DFS的细节:
如果一张牌出现【超过或等于】3次,他都有可能凑成一个3张相同的坎牌,但也有可能不
如果一张牌出现【超过或等于】2次,他都有可能凑成一个对牌,但也有可能不
如果一张牌出现【超过或等于】1次,他都有可能凑成一个3张连续的坎牌,但也有可能不
如果一张牌出现【只有】1次,他【只可能】凑成一个3张连续的坎牌
所以在DFS实现过程中,我们要把每种情况尝试一遍,统计坎牌和对牌的出现次数
有一个特例:
1W1W2W2W3W3W4W4W5T6T6T7T7T8T
这里的1W2W3W4W四张牌均有2个相同,他们既有可能作为坎牌也有可能作为对牌
遇到这种情况,我们从小到大遍历时,优先考虑坎牌的情况(一点点贪心?不证明了,但应该是对的。)
核心代码用伪代码表示大概是
pair<int, int> get(int num[]) {
int cnt2 = 0, cnt3 = 0, sum = 0;
for(int i = 1; i <= 29; ++i)
sum += num[i];
for(int i = 1; i <= 29; ++i) {
if(!num[i]) continue;
switch(num[i]) {
case 4:
case 3:
尝试用3张相同的牌作为坎牌
case 2: {
if(i < 28 && num[i+1] >= 1 && num[i+2] >= 1) {
尝试用3张连续的牌作为坎牌
}
尝试用2张相同的牌作为对牌
break;
}
case 1: {
if(i < 28 && num[i+1] >= 1 && num[i+2] >= 1) {
尝试用3张连续的牌作为坎牌
}
else
return make_pair(0, 0);
}
}
}
return make_pair(0, 0);
} 然后是完整代码
#include<bits/stdc++.h>
using namespace std;
int getId(char num, char type) {
if(type == 'W')
return num - '0';
if(type == 'T')
return num - '0' + 10;
else
return num - '0' + 20;
}
bool judge(int id, char type) {
if(1 <= id && id <= 9 && type == 'W')
return true;
if(11 <= id && id <= 19 && type == 'T')
return true;
if(21 <= id && id <= 29 && type == 'S')
return true;
return false;
}
map<int, int> mp;
pair<int, int> get(int num[]) {
int cnt2 = 0, cnt3 = 0, sum = 0;
for(int i = 1; i <= 29; ++i)
sum += num[i];
for(int i = 1; i <= 29; ++i) {
if(!num[i]) continue;
switch(num[i]) {
case 4:
case 3: {
num[i] -= 3; ++cnt3;
pair<int, int> pr = get(num);
cnt2 += pr.first;
cnt3 += pr.second;
if(2*cnt2 + 3*cnt3 == sum)
return make_pair(cnt2, cnt3);
cnt2 -= pr.first;
cnt3 -= pr.second;
num[i] += 3; --cnt3;
}
case 2: {
if(i < 28 && num[i+1] >= 1 && num[i+2] >= 1) {
--num[i]; --num[i+1]; --num[i+2]; ++cnt3;
pair<int, int> pr = get(num);
cnt2 += pr.first;
cnt3 += pr.second;
if(2*cnt2 + 3*cnt3 == sum)
return make_pair(cnt2, cnt3);
cnt2 -= pr.first;
cnt3 -= pr.second;
++num[i]; ++num[i+1]; ++num[i+2]; --cnt3;
}
num[i] -= 2; ++cnt2;
pair<int, int> pr = get(num);
cnt2 += pr.first;
cnt3 += pr.second;
if(2*cnt2 + 3*cnt3 == sum)
return make_pair(cnt2, cnt3);
cnt2 -= pr.first;
cnt3 -= pr.second;
num[i] += 2; --cnt2;
break;
}
case 1: {
if(i < 28 && num[i+1] >= 1 && num[i+2] >= 1) {
--num[i]; --num[i+1]; --num[i+2]; ++cnt3;
pair<int, int> pr = get(num);
cnt2 += pr.first;
cnt3 += pr.second;
if(2*cnt2 + 3*cnt3 == sum)
return make_pair(cnt2, cnt3);
cnt2 -= pr.first;
cnt3 -= pr.second;
++num[i]; ++num[i+1]; ++num[i+2]; --cnt3;
}
else
return make_pair(0, 0);
}
}
}
return make_pair(0, 0);
}
pair<int, int> judge() {
int num[30]; memset(num, 0, sizeof(num));
for(int i = 1; i <= 29; ++i)
num[i] = mp[i];
pair<int, int> ans = get(num);
return ans;
}
void printMap() {
printf("=============\n");
for(auto it = mp.begin(); it != mp.end(); ++it)
printf("%d->%d\n", it->first, it->second);
printf("=============\n");
}
int main() {
int n;
while(cin>>n) {
char que; cin>>que;
while(n--) {
mp.clear();
bool mark = true;
char pai[50]; cin>>pai;
for(int i = 0; i < 14; ++i) {
int id = getId(pai[i*2], pai[i*2 + 1]);
if(judge(id, que)) {
mark = false;
break;
}
mp[id]++;
}
if(mark) {
pair<int, int> pr = judge();
int cnt2 = pr.first;
int cnt3 = pr.second;
if(!(cnt2 == 7 || (cnt2 == 1 && cnt3 == 4)))
mark = false;
}
printf(mark ? "Yes\n" : "No\n");
}
}
return 0;
} 


京公网安备 11010502036488号