【题目链接】
除过顺子的那些带牌和单打,可以直接算出来,得到一个答案的上界。
搜索时候只要找顺子,顺带剪几个枝就行了。
交上去rank1,吓傻。
/* Pigonometry */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 18; int n, a[maxn], cnt[5], ans; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline int calc(int x[]) { memset(cnt, 0, sizeof(cnt)); int res = 0; for(int i = 0; i < maxn; i++) cnt[x[i]]++; while(cnt[4] && cnt[2] >= 2) res++, cnt[4]--, cnt[2] -= 2; while(cnt[4] && cnt[1] >= 2) res++, cnt[4]--, cnt[1] -= 2; while(cnt[3] && cnt[2] >= 1) res++, cnt[3]--, cnt[2] -= 1; while(cnt[3] && cnt[1] >= 1) res++, cnt[3]--, cnt[1] -= 1; return res + cnt[1] + cnt[2] + cnt[3] + cnt[4]; } inline void dfs(int x[], int step) { if(step > ans) return; ans = min(ans, step + calc(x)); for(int i = 2, j; i < maxn; i++) { for(j = i; x[j] >= 3; j++); if(j - i >= 2) { for(int t = j; t - i >= 2; t--) { for(int k = i; k < t; k++) x[k] -= 3; dfs(x, step + 1); for(int k = i; k < t; k++) x[k] += 3; } } } for(int i = 2, j; i < maxn; i++) { for(j = i; x[j] >= 2; j++); if(j - i >= 3) { for(int t = j; t - i >= 3; t--) { for(int k = i; k < t; k++) x[k] -= 2; dfs(x, step + 1); for(int k = i; k < t; k++) x[k] += 2; } } } for(int i = 2, j; i < maxn; i++) { for(j = i; x[j] >= 1; j++); if(j - i >= 5) { for(int t = j; t - i >= 5; t--) { for(int k = i; k < t; k++) x[k] -= 1; dfs(x, step + 1); for(int k = i; k < t; k++) x[k] += 1; } } } } int main() { int T = iread(), n = iread(); while(T--) { memset(a, 0, sizeof(a)); for(int i = 1; i <= n; i++) { int w = iread(), c = iread(); if(w == 1) w = 13; else if(w) w--; a[w]++; } ans = calc(a); dfs(a, 0); printf("%d\n", ans); } return 0; }