【LOJ】#6434. 「PKUSC2018」主鬥地
阿新 • • 發佈:2018-12-14
題解
什麼,我這題竟然快到了LOJ rk1????
搜起來有點麻煩,不過感覺還是比鬥地主好下手(至今沒敢寫鬥地主
首先是暴力搜牌型,最多\(3^16\)(什麼判解還要複雜度慫成一團)的樣子??
然後判牌型,顯然只要考慮單牌,和3 + x,4+2
然後暴力搜網友的3和4
暴力搜jry的3和4
然後列舉3搭配了幾個2,
然後jry從大到小開始去除大小為2的對子,網友從小到大,是個簡單的貪心
之後看看可以去掉的單牌的個數,也是jry從大到小,網友從小到大
之後的就是單牌互相壓看看合不合法就好了
程式碼
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } char s[20]; int rem[16],A[16],W[16],K[16],ans,jry[16]; int C[16],D[16],H[16],J[16],P[16]; int code(char c) { if(c >= '4' && c <= '9') return c - '4' + 1; if(c == 'T') return 7; if(c == 'J') return 8; if(c == 'Q') return 9; if(c == 'K') return 10; if(c == 'A') return 11; if(c == '2') return 12; if(c == 'w') return 13; if(c == 'W') return 14; } bool check(int f,int t) { for(int i = 0 ; i <= t ; ++i) { memcpy(H,W,sizeof(H)); memcpy(J,K,sizeof(K)); if(2 * i + t - i + f * 2 + f * 4 + t * 3 > 17) break; int cnt = 0; for(int j = 1 ; j <= 14 ; ++j) { if(H[j] >= 2 && cnt < i) {H[j] -= 2;++cnt;} if(H[j] >= 2 && cnt < i) {H[j] -= 2;++cnt;} if(cnt == i) break; } if(cnt < i) break; cnt = 0; for(int j = 14 ; j >= 1 ; --j) { if(J[j] >= 2 && cnt < i) {J[j] -= 2;++cnt;} if(J[j] >= 2 && cnt < i) {J[j] -= 2;++cnt;} if(cnt == i) break; } if(cnt < i) break; memset(P,0,sizeof(P)); cnt = 2 * f + t - i; for(int j = 14 ; j >= 1 ; --j) { int t = min(cnt,J[j]); J[j] -= t;cnt -= t; if(cnt == 0) break; } if(cnt) continue; cnt = 2 * f + t - i; for(int j = 1 ; j <= 14 ; ++j) { int t = min(cnt,H[j]); H[j] -= t;cnt -= t; if(cnt == 0) break; } if(J[14]) continue; for(int j = 1 ; j <= 14 ; ++j) { P[j] += H[j]; P[j + 1] -= J[j]; } cnt = 0; for(int j = 1 ; j <= 14 ; ++j) { cnt += P[j]; if(cnt > 0) break; } if(cnt == 0) return true; } return false; } bool brute_jry(int dep,int four,int three,int f,int t,int q1,int q2) { if(four == f && t == three) return check(four,three); if(dep >= 12) return false; q1 += C[dep];q2 += D[dep]; if(q1 > 0 || q2 > 0) return false; if(K[dep] >= 3) { K[dep] -= 3; if(brute_jry(dep + 1,four,three,f,t + 1,q1 - 1,q2)) return true; K[dep] += 3; } if(K[dep] >= 4) { K[dep] -= 4; if(brute_jry(dep + 1,four,three,f + 1,t,q1,q2 - 1)) return true; K[dep] += 4; } return brute_jry(dep + 1,four,three,f,t,q1,q2); } bool brute_wangyou(int dep,int four,int three) { if(four * 6 + three * 4 > 17) return false; if(dep > 12) { if(brute_jry(1,four,three,0,0,0,0)) return true; return false; } if(W[dep] >= 3) { W[dep] -= 3;++C[dep]; if(brute_wangyou(dep + 1,four,three + 1)) return true; W[dep] += 3;--C[dep]; } if(W[dep] >= 4) { W[dep] -= 4;++D[dep]; if(brute_wangyou(dep + 1,four + 1,three)) return true; W[dep] += 4;--D[dep]; } if(brute_wangyou(dep + 1,four,three)) return true; return false; } void dfs(int dep,int r) { if(!r) { memset(C,0,sizeof(C)); memset(D,0,sizeof(D)); memcpy(W,A,sizeof(A)); memcpy(K,jry,sizeof(jry)); if(brute_wangyou(2,0,0)) {++ans;} return; } if(dep > 14) return; for(int i = 0 ; i <= rem[dep] ; ++i) { if(i > r) break; jry[dep] = i; dfs(dep + 1,r - i); jry[dep] = 0; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif while(scanf("%s",s + 1) != EOF) { memset(A,0,sizeof(A)); for(int i = 1 ; i <= 12 ; ++i) rem[i] = 4; rem[13] = rem[14] = 1; ans = 0; for(int i = 1 ; i <= 17 ; ++i) { A[code(s[i])]++;rem[code(s[i])]--; } dfs(1,17); out(ans);enter; } }