16级赵子潇 • 4年前
#include<bits/stdc++.h>
using namespace std;
const int N = 30;
const int inf = 0x3f3f3f3f;
int T, n, a[N], ans;//a[i]表示数码为i的牌有多少张
void dfs(int sum, int step){//还有多少张牌,出了多少次
if(sum == 0){
ans = min(ans, step);
return ;
}
if(step >= ans)return ;
//三顺子
for(int i = 3;i <= 13;i++){//起点
if(a[i] < 3)continue;
for(int len = 2;i + len - 1 <= 14;len++){
if(a[i + len - 1] >= 3){
for(int j = i;j <= i + len - 1;j++)a[j] -= 3;
dfs(sum - len * 3, step + 1);
for(int j = i;j <= i + len - 1;j++)a[j] += 3;
}else break;
}
}
//双顺子
for(int i = 3;i <= 12;i++){//起点
if(a[i] < 2 || a[i + 1] < 2)continue;
for(int len = 3;i + len - 1 <= 14;len++){
if(a[i + len - 1] >= 2){
for(int j = i;j <= i + len - 1;j++)a[j] -= 2;
dfs(sum - len * 2, step + 1);
for(int j = i;j <= i + len - 1;j++)a[j] += 2;
}else break;
}
}
//单顺子
for(int i = 3;i <= 10;i++){//起点
if(a[i] < 1 || a[i + 1] < 1 || a[i + 2] < 1 || a[i + 3] < 1)continue;
for(int len = 5;i + len - 1 <= 14;len++){
if(a[i + len - 1] >= 1){
for(int j = i;j <= i + len - 1;j++)a[j] -= 1;
dfs(sum - len * 1, step + 1);
for(int j = i;j <= i + len - 1;j++)a[j] += 1;
}else break;
}
}
//四
for(int i = 3;i <= 15;i++){
if(a[i] < 4)continue;
//两张单牌
for(int j = 3;j <= 17;j++){
if(j == i || a[j] < 1)continue;
for(int k = 3;k <= 17;k++){
if(k == i || a[k] < 1 || (k == j && a[j] == 1))continue;
a[i] -= 4;
a[j] -= 1;
a[k] -= 1;
dfs(sum - 6, step + 1);
a[i] += 4;
a[j] += 1;
a[k] += 1;
}
}
//两张对牌
for(int j = 3;j <= 15;j++){
if(j == i || a[j] < 2)continue;
for(int k = 3;k <= 15;k++){
if(k == i || a[k] < 2 || (k == j && a[j] < 4))continue;
a[i] -= 4;
a[j] -= 2;
a[k] -= 2;
dfs(sum - 8, step + 1);
a[i] += 4;
a[j] += 2;
a[k] += 2;
}
}
}
//三
for(int i = 3;i <= 15;i++){
if(a[i] < 3)continue;
//带二
for(int j = 3;j <= 15;j++){
if(i == j || a[j] < 2)continue;
a[i] -= 3;
a[j] -= 2;
dfs(sum - 5, step + 1);
a[i] += 3;
a[j] += 2;
}
//带一、炸弹
for(int j = 3;j <= 17;j++){
if(a[j] < 1 || (i == j && a[i] < 4))continue;
a[i] -= 3;
a[j] -= 1;
dfs(sum - 4, step + 1);
a[i] += 3;
a[j] += 1;
}
//不带
a[i] -= 3;
dfs(sum - 3, step + 1);
a[i] += 3;
}
//先对子、火箭,最后单牌
for(int i = 3;i <= 15;i++){
if(a[i] < 2)continue;
++step;
sum -= 2;
}
if(a[16] && a[17]){
++step;
sum -= 2;
}
ans = min(ans, step + sum);
}
int main()
{
freopen("data.in", "r", stdin);
scanf("%d%d", &T, &n);
while(T--){
memset(a, 0, sizeof(a));
for(int i = 1;i <= n;i++){
int A, B;
scanf("%d%d", &A, &B);
if(A == 0)A = 15 + B;
else if(A == 1 || A == 2)A += 13;
++a[A];
}
ans = inf;
dfs(n, 0);
printf("%d\n", ans);
}
return 0;
}
评论: