打牌技术不精,没有把$A$放在顺子里面搜,WA了好长时间。
盗用大佬的一张图:
当时自己搜的时候没有把四张牌拆成三带一等情况。
然后还有一点就是四张三张都出完之后直接数一数剩下的一张两张牌还要多少次出完就好了,没有必要浪费栈空间和递归深度去搜这些东西。(我就是这样T了好多次QωQ)。
要注意暴力算的前提就是一定要把之前的三张四张打完。
玄学复杂度。
代码很丑很长。
Code:
#include <cstdio> #include <cstring> using namespace std; const int N = 20; const int inf = 1 << 30; int testCase, n, cnt[N], ans; inline void read(int &X) { X = 0; char ch = 0; int op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } inline void chkMin(int &x, int y) { if(y < x) x = y; } void dfs(int rest, int stp) { if(stp >= ans) return; if(rest == 0) { chkMin(ans, stp); return; } /* for(int j, i = 3; i <= 14; i++) { if(cnt[i] < 1) continue; for(j = i; j <= 14; j++) if(cnt[j] < 1) break; j--; if(j - i + 1 < 5) { i = j; continue; } for(int k = i; k <= j; k++) --cnt[k]; dfs(rest - (j - i + 1), stp + 1); for(int k = i; k <= j; k++) ++cnt[k]; i = j; } for(int j, i = 3; i <= 14; i++) { if(cnt[i] < 2) continue; for(j = i; j <= 14; j++) if(cnt[j] < 2) break; j--; if(j - i + 1 < 3) { i = j; continue; } for(int k = i; k <= j; k++) cnt[k] -= 2; dfs(rest - (j - i + 1) * 2, stp + 1); for(int k = i; k <= j; k++) cnt[k] += 2; i = j; } for(int j, i = 3; i <= 14; i++) { if(cnt[i] < 3) continue; for(j = i; j <= 14; j++) if(cnt[j] < 3) break; j--; if(j - i + 1 < 2) { i = j; continue; } for(int k = i; k <= j; k++) cnt[k] -= 3; dfs(rest - (j - i + 1) * 3, stp + 1); for(int k = i; k <= j; k++) cnt[k] += 3; i = j; } */ /* for(int j, k, i = 2; i <= 14; i++) { if(cnt[i] < 4) continue; for(j = 2; j <= 15; j++) { if(j == i) continue; if(cnt[j] > 1) { for(k = 2; k <= 15; k++) { if(k == i) continue; if(cnt[k] > 1) { cnt[i] -= 4, cnt[j] -= 2, cnt[k] -= 2; dfs(rest - 8, stp + 1); cnt[i] += 4, cnt[j] += 2, cnt[k] += 2; } } } } } for(int j, k, i = 2; i <= 14; i++) { if(cnt[i] < 4) continue; for(j = 2; j <= 15; j++) { if(j == i) continue; if(cnt[j] > 0) { for(k = 2; k <= 15; k++) { if(k == i) continue; if(cnt[k] > 0) { cnt[i] -= 4, --cnt[j], --cnt[k]; dfs(rest - 6, stp + 1); cnt[i] += 4, ++cnt[j], ++cnt[k]; } } } } } for(int i = 2; i <= 14; i++) { if(cnt[i] < 4) continue; cnt[i] -= 4; dfs(rest - 4, stp + 1); cnt[i] += 4; } for(int j, i = 2; i <= 14; i++) { if(cnt[i] < 3) continue; for(j = 2; j <= 15; j++) { if(j == i) continue; if(cnt[j] > 1) { cnt[i] -= 3, cnt[j] -= 2; dfs(rest - 5, stp + 1); cnt[i] += 3, cnt[j] += 2; } } } for(int j, i = 2; i <= 14; i++) { if(cnt[i] < 3) continue; for(j = 2; j <= 15; j++) { if(j == i) continue; if(cnt[j] > 0) { cnt[i] -= 3, --cnt[j]; dfs(rest - 4, stp + 1); cnt[i] += 3, ++cnt[j]; } } } for(int i = 2; i <= 14; i++) { if(cnt[i] < 3) continue; cnt[i] -= 3; dfs(rest - 3, stp + 1); cnt[i] += 3; } */ int len = 0; for(int i = 3; i <= 14; i++) { if(cnt[i] == 0) len = 0; else { ++len; if(len >= 5) { for(int j = i; j >= i - len + 1; j--) cnt[j]--; dfs(rest - len, stp + 1); for(int j = i; j >= i - len + 1; j--) cnt[j]++; } } } len = 0; for(int i = 3; i <= 14; i++) { if(cnt[i] <= 1) len = 0; else { ++len; if(len >= 3) { for(int j = i; j >= i - len + 1; j--) cnt[j] -= 2; dfs(rest - len * 2, stp + 1); for(int j = i; j >= i - len + 1; j--) cnt[j] += 2; } } } len = 0; for(int i = 3; i <= 14; i++) { if(cnt[i] <= 2) len = 0; else { len++; if(len >= 2) { for(int j = i; j >= i - len + 1; j--) cnt[j] -= 3; dfs(rest - len * 3, stp + 1); for(int j = i; j >= i - len + 1; j--) cnt[j] += 3; } } } for(int i = 2; i <= 14; i++) { if(cnt[i] <= 3) { if(cnt[i] <= 2) continue; cnt[i] -= 3; for(int j = 2; j <= 15; j++) { if(j == i || cnt[j] == 0) continue; cnt[j]--; dfs(rest - 4, stp + 1); cnt[j]++; } for(int j = 2; j <= 15; j++) { if(j == i || cnt[j] <= 1) continue; cnt[j] -= 2; dfs(rest - 5, stp + 1); cnt[j] += 2; } cnt[i] += 3; } else { cnt[i] -= 3; for(int j = 2; j <= 15; j++) { if(j == i || cnt[j] == 0) continue; cnt[j]--; dfs(rest - 4, stp + 1); cnt[j]++; } for(int j = 2; j <= 15; j++) { if(j == i || cnt[j] <= 1) continue; cnt[j] -= 2; dfs(rest - 5, stp + 1); cnt[j] += 2; } cnt[i] += 3; cnt[i] -= 4; for(int j = 2; j <= 15; j++) { if(j == i || cnt[j] == 0) continue; cnt[j]--; for(int k = 2; k <= 15; k++) { if(k == j || cnt[k] == 0) continue; cnt[k]--; dfs(rest - 6, stp + 1); cnt[k]++; } cnt[j]++; } for(int j = 2; j <= 14; j++) { if(j == i || cnt[j] <= 1) continue; cnt[j] -= 2; for(int k = 2; k <= 14; k++) { if(k == j || cnt[k] <= 1) continue; cnt[k] -= 2; dfs(rest - 8, stp + 1); cnt[k] += 2; } cnt[j] += 2; } cnt[i] += 4; } } int now = 0; for(int i = 2; i <= 15; i++) if(cnt[i]) ++now; chkMin(ans, stp + now); } int main() { // freopen("Sample.txt", "r", stdin); // freopen("testdata.in", "r", stdin); // freopen("my.txt", "w", stdout); read(testCase), read(n); for(; testCase--; ) { memset(cnt, 0, sizeof(cnt)); for(int x, y, i = 1; i <= n; i++) { read(x), read(y); if(x == 0) cnt[15]++; else { if(x == 1) cnt[14]++; else cnt[x]++; } } ans = inf; dfs(n, 0); printf("%d\n", ans); } return 0; }