果然对状压DP,我根本就不懂=。=
/**************************************************
Problem: 2923 User: G_lory
Memory: 720K Time: 157MS
Language: G++ Result: Accepted
**************************************************/
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 1 << 11;
const int INF = 0x5f5f5f5f;
int n, c1, c2;
int w[12];
int dp[MAXN];
int vis[MAXN];
int bag[MAXN];
bool ok(int st)
{
memset(vis, 0, sizeof vis);
vis[0] = 1;
int sum = 0;
for (int i = 0; i < n; ++i)
{
if ((1 << i) & st)//if (i & n)
{
sum += w[i];
if (sum > c1 + c2) return false;// 很好理解,如果比两个车装的物体和还大,不可能一次装完
for (int j = c1; j >= w[i]; --j)
{
if (vis[j - w[i]]) // 对n这个状态含有的物体做01背包,
vis[j] = 1; // vis[j]=1表示物体可以刚好组成j,且j可以c1被装下
}
}
}
for (int i = 0; i <= c1; ++i) // 就是看sum能否被两车一次装下
if (sum - i <= c2 && vis[i]) return true;
return false;
}
int main()
{
int t;
scanf("%d", &t);
for (int cas = 1; cas <= t; ++cas)
{
scanf("%d%d%d", &n, &c1, &c2);
for (int i = 0; i < n; ++i)
{
scanf("%d", &w[i]);
}
int st = (1 << n) - 1;
int cnt = 0;
for (int i = 1; i <= st; ++i)
{
if (ok(i))
{
bag[cnt++] = i;
}
}
for (int i = 1; i <= st; ++i) dp[i] = INF;
dp[0] = 0;
for (int i = 0; i < cnt; ++i)
{
for (int j = st; j >= 0; --j)
{
if (dp[j] != INF && (j & bag[i]) == 0)
{
dp[j | bag[i]] = min(dp[j | bag[i]], dp[j] + 1);
}
}
}
printf("Scenario #%d:\n%d\n\n", cas, dp[st]);
}
return 0;
}