这是一道DP问题,觉得挺有意思的,所以时隔数日又写了一遍……
#include<iostream>
#include<cstdio>
using namespace std;
int dp[20][20][20][20];
int a[20];
int main()
{
int f,i,j,k;
int t, cases;
scanf("%d", &cases);
t = 1;
while(t <= cases)
{
int c,m;
scanf("%d %d", &c, &m);
memset(a, 0, sizeof(a));
int tmp;
for(i=0; i<m; i++)
{
scanf("%d", &tmp);
a[tmp] ++;
}
memset(dp, -1, sizeof(dp));
dp[1][0][0][0] = 0;
for(f=2; f<=16; f++)
for(i=0; i<=c; i++)
for(j=0; j<=c; j++)
for(k=0; k<=c; k++)
{
if(dp[f-1][i][j][k] == -1) continue;
int x,y,z;
for(x=0; x<=a[f]; x++)
for(y=0; y<=a[f]; y++)
{
z = a[f] - x - y;
if(x + y > a[f]) continue;
if(x+i > c|| y+j>c || z+k > c) continue;
tmp = dp[f-1][i][j][k] + (x!=0)+(y!=0)+(z!=0);
if(dp[f][x+i][y+j][z+k] == -1 || dp[f][x+i][y+j][z+k] > tmp)
dp[f][x+i][y+j][z+k] = tmp;
}
}
int res = 10000000;
for(i=0; i<=c; i++)
for(j=0; j<=c; j++)
{
if(i+j>m) continue;
if(dp[16][i][j][m-i-j] == -1) continue;
if(dp[16][i][j][m-i-j] < res)
res = dp[16][i][j][m-i-j];
}
printf("Case %d: %d\n", t, res);
t ++;
}
return 0;
}