48pts了
```cpp
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int s = 0, w = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}
return s * w;
}
int T, n, a[16], ans = 0x3f3f3f;
inline void dfs(int step, int sum)
{
if(step >= ans) return ;
if(sum > n) return ;
if(sum == n)
{
ans = min(step, ans);
return ;
}
for(int i = 2;i <= 15;i ++)
{
if(a[i] >= 4)
{
a[i] -= 4;
for(int j = 2;j <= 15;j ++)
{
if(i == j) continue;
if(a[j] >= 1)
{
a[j] -= 1;
for(int k = 2;k <= 15;k ++)
{
if(k == i) continue;
if(a[k] >= 1)
{
a[k] --;
dfs(step + 1, sum + 6);
a[k] ++;
}
}
a[j] ++;
}//四带二单
if(a[j] >= 2 && j != 15)
{
a[j] -= 2;
for(int k = 2;k <= 14;k ++)
{
if(k == i) continue;
if(a[k] >= 2)
{
a[k] -= 2;
dfs(step + 1, sum + 8);
a[k] += 2;
}
}
a[j] += 2;//四带二对
}
}
dfs(step + 1, sum + 4);//炸弹
a[i] += 4;
}
if(i != 2 && i != 15)
{
if(a[i] >= 3)
{
a[i] -= 3;
int y = 1;
for(int j = i + 1;j <= 14;j ++)
if(a[j] >= 3) y ++;
else break;
if(y >= 2)
{
for(int j = i + 1;j <= i + y - 1;j ++) a[j] -= 3;
dfs(step + 1, sum + y * 3);
for(int j = i + 1;j <= i + y - 1;j ++) a[j] += 3;
}
a[i] += 3;//三顺子
}
else if(a[i] >= 2)
{
a[i] -= 2;
int y = 1;
for(int j = i + 1;j <= 14;j ++)
if(a[j] >= 2) y ++;
else break;
if(y >= 3)
{
for(int j = i + 1;j <= i + y - 1;j ++) a[j] -= 2;
dfs(step + 1, sum + y * 2);
for(int j = i + 1;j <= i + y - 1;j ++) a[j] += 2;
}
a[i] += 2;//双顺子
}
else if(a[i] >= 1)
{
a[i] --;
int y = 1;
for(int j = i + 1;j <= 14;j ++)
if(a[j] >= 1) y ++;
else break;
if(y >= 5)
{
for(int j = i + 1;j <= i + y - 1;j ++) a[j] --;
dfs(step + 1, sum + y);
for(int j = i + 1;j <= i + y - 1;j ++) a[j] ++;
}
a[i] ++;//单顺子
}
}
if(a[i] >= 3)
{
a[i] -= 3;
for(int j = 2;j <= 15;j ++)
{
if(i == j) continue;
if(a[j] >= 2 && j != 15)
{
a[j] -= 2;
dfs(step + 1, sum + 5);
a[j] += 2;//三带二
}
if(a[j] >= 1)
{
a[j] --;
dfs(step + 1, sum + 4);
a[j] ++;//三带一
}
}
dfs(step + 1, sum + 3);//三张牌
a[i] += 3;
}
if(a[i] >= 2)
{
a[i] -= 2;
dfs(step + 1, sum + 2);
a[i] += 2;
}//对子
if(a[i] >= 1)
{
a[i] --;
dfs(step + 1, sum + 1);
a[i] ++;
}//单张
}
}
int main()
{
T = read(), n = read();
while(T --)
{
for(int i = 1;i <= n;i ++)
{
int x = read(), y = read();
if(x == 0) a[15] ++;
else if(x == 1) a[14] ++;
else a[x] ++;
}
dfs(0, 0);
cout << ans << endl;
for(int i = 1;i <= 15;i ++) a[i] = 0;
ans = 0x3f3f3f;
}
return 0;
}
```
~~验证码tkkk寄~~
by Killua_Zaoldyeck @ 2023-07-12 16:27:25
@[5k_sync_closer](/user/388651) 5k救我!
by Killua_Zaoldyeck @ 2023-07-12 16:53:51
不调大模拟
by 5k_sync_closer @ 2023-07-12 16:54:36
@[5k_sync_closer](/user/388651) 恼
by Killua_Zaoldyeck @ 2023-07-12 16:59:29
@[02yyds](/user/728127) 调好了,改了一大堆东西,顺便把TLE搞没了
```cpp
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int s = 0, w = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}
return s * w;
}
int T, n, a[16], ans = 0x3f3f3f,b[101][25],vis[101];
inline void dfs(int step)
{
if(step >= ans) return ;
for(int i = 2;i <= 15;i ++)
{
if(a[i] >= 4)
{
a[i] -= 4;
for(int j = 2;j <= 15;j ++)
{
if(i == j) continue;
if(a[j] >= 1)
{
a[j] --;
for(int k = 2;k <= 15;k ++)
{
if(k == i) continue;
if(a[k] >= 1)
{
a[k] --;
dfs(step + 1);
a[k] ++;
}
}
a[j] ++;
}//四带二单
if(a[j] >= 2 && j != 15)
{
a[j] -= 2;
for(int k = 2;k <= 14;k ++)
{
if(k == i) continue;
if(a[k] >= 2)
{
a[k] -= 2;
dfs(step + 1);
a[k] += 2;
}
}
a[j] += 2;//四带二对
}
}
a[i] += 4;
}
if(a[i] >= 3 && i!=2 && i!=15)
{
a[i] -= 3;
int y = 1;
for(int j = i + 1;j <= 14;j ++)
{
if(a[j] >= 3) y ++;
else break;
if(y >= 2)
{
for(int j = i + 1;j <= i + y - 1;j ++) a[j] -= 3;
dfs(step + 1);
for(int j = i + 1;j <= i + y - 1;j ++) a[j] += 3;
}
}
a[i] += 3;//三顺子
}
if(a[i] >= 2 && i!=2 && i!=15)
{
a[i] -= 2;
int y = 1;
for(int j = i + 1;j <= 14;j ++)
{
if(a[j] >= 2) y ++;
else break;
if(y >= 3)
{
for(int j = i + 1;j <= i + y - 1;j ++) a[j] -= 2;
dfs(step + 1);
for(int j = i + 1;j <= i + y - 1;j ++) a[j] += 2;
}
}
a[i] += 2;//双顺子
}
if(a[i] >= 1 && i!=2 && i!=15)
{
a[i] --;
int y = 1;
for(int j = i + 1;j <= 14;j ++)
{
if(a[j] >= 1) y ++;
else break;
if(y >= 5)
{
for(int j = i + 1;j <= i + y - 1;j ++) a[j] --;
dfs(step + 1);
for(int j = i + 1;j <= i + y - 1;j ++) a[j] ++;
}
}
a[i] ++;//单顺子
}
if(a[i] >= 3)
{
a[i] -= 3;
for(int j = 2;j <= 15;j ++)
{
if(i == j) continue;
if(a[j] >= 2 && j != 15)
{
a[j] -= 2;
dfs(step + 1);
a[j] += 2;//三带二
}
if(a[j] >= 1)
{
a[j] --;
dfs(step + 1);
a[j] ++;//三带一
}
}
a[i] += 3;
}
}
for(int i=2;i<=15;i++)
if(a[i])
step++;
ans=min(step,ans);
}
int main()
{
T = read(), n = read();
int st=T;
while(T --)
{
for(int i = 1;i <= 15;i ++)a[i] = 0;
for(int i = 1;i <= n;i ++)
{
int x = read(), y = read();
if(x == 0) b[T+1][15]++,a[15] ++;
else if(x == 1) b[T+1][14]++,a[14] ++;
else a[x] ++,b[T+1][x]++;
}
int flag=0;
for(int i=st;i>T+1;i--)
{
bool y=true;
for(int j=2;j<=15;j++)
if(b[i][j]!=a[j])
{
y=false;
break;
}
if(y)
{
flag=i;
break;
}
}
if(flag)
cout<<vis[flag]<<endl;
else
{
dfs(0);
vis[T+1]=ans;
cout<<ans<<endl;
}
ans = 0x3f3f3f;
}
return 0;
}
```
主要的问题:
1.顺子不要用if...else if...连起来,每种顺子都要枚举。
2.顺子不能用2。
3.不用记录用了几张,因为1张2张3张4张都可以直接出,所以最后直接将这些牌都出掉,不需要再递归,还少了一个变量。
```cpp
for(int i=2;i<=15;i++)
if(a[i])
step++;
```
优化:
加了一个类似记忆化的数组,因为#25的数据长这样:
```
10 23
12 1
11 4
5 3
10 4
4 2
12 3
6 4
8 3
10 2
12 4
9 1
6 1
4 1
8 4
7 3
6 3
7 1
4 4
7 2
0 2
8 1
1 3
6 2
12 1
......
```
out
```
5
5
5
5
5
5
5
5
5
5
```
这是一模一样的10个数据
by qiuqiuqzm @ 2023-07-18 17:38:28
@[qiuqiuqzm](/user/658945) 謝謝,關注了
by Killua_Zaoldyeck @ 2023-07-18 17:58:40