题意:如果摸到的14张麻将,可以组成4副三张麻将连续或者相同的,以及两个一样的就能获胜。
思路:直接暴力枚举每种可以摸到的牌型,用dfs判断当前拿到的14张牌型能否获胜。
如果搜索时不优化会超时,如果你选择了第cur张牌,那么你下次不必再选择cur以前的牌,因为会造成重复搜索。加上这个剪枝就能过掉。我还自己加了一个剪枝:先排序,然后如果组合到第cur张牌,前面还有牌没有组合,说明不可能组合完,因为每张牌只会和它自身以及比它更大的牌组合。
字符的处理:s、b、c看做0,1,2,那么1s就表示10,5b表示51,就能愉快地转换成数字了。
AC代码:78ms
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <utility> #include <string> #include <iostream> #include <map> #include <set> #include <vector> #include <queue> #include <stack> using namespace std; #define eps 1e-10 #define inf 0x3f3f3f3f #define PI pair<int, int> typedef long long LL; const int maxn = 100+5; char p[] = {'s', 'b', 'c'}; int vis[maxn], cnt[maxn], a[20]; bool dfs(int k, int cur) { for(int i = 0; i < cur; ++i) { //剪枝 if(cnt[a[i]]) return false; } if(k == 5) return true; if(k == 0) { for(int i = 0; i < 14; ++i) { int x = a[i]; if(cnt[x] >= 2 && !vis[x]) { vis[x] = 1; cnt[x] -= 2; if(dfs(k+1, cur)) return true; cnt[x] += 2; } } } else { for(int i = cur; i < 14; ++i) { int x = a[i]; //取三个一样的 if(cnt[x] >= 3) { cnt[x] -= 3; if(dfs(k+1, i)) return true; cnt[x] += 3; } //取三个连续的 int y = x / 10, z = x % 10; if(y + 2 <= 9) { int flag = 1; for(int j = 0; j < 3; ++j) { if(!cnt[(y+j)*10+z]) { flag = 0; break; } } if(flag) { for(int j = 0; j < 3; ++j) cnt[(y+j)*10+z]--; if(dfs(k+1, i)) return true; for(int j = 0; j < 3; ++j) cnt[(y+j)*10+z]++; } } } } return false; } int main() { char ma[5]; int T, kase = 1; scanf("%d", &T); while(T--) { memset(cnt, 0, sizeof(cnt)); for(int i = 0; i < 13; ++i) { scanf("%s", ma); for(int j = 0; j < 3; ++j) { if(ma[1] == p[j]) { a[i] = (ma[0]-'0')*10+j; cnt[a[i]]++; } } } int old[maxn] , b[maxn]; memcpy(old, cnt, sizeof(cnt)); memcpy(b, a, sizeof(a)); printf("Case %d:", kase++); int ans = 0; for(int i = 0; i <= 2; ++i) for(int j = 1; j <= 9; ++j) { int x = j * 10 + i; if(cnt[x] == 4) continue; memset(vis, 0, sizeof(vis)); memcpy(cnt, old, sizeof(old)); memcpy(a, b, sizeof(a)); a[13] = x; sort(a, a+14); cnt[x]++; if(dfs(0, 0)) { ++ans; printf(" %d%c", j, p[i]); } } if(!ans) printf(" None"); printf("\n"); } return 0; }
如有不当之处欢迎指出!