题目链接:
http://cstest.scu.edu.cn/soj/problem.action?id=4116
题目大意:
给你N块宽度为1、长度不等的巧克力。
再给你一个1*L的盒子。
问最少放进去多少块巧克力,就使得剩下的巧克力一块都放不进去了。
算法:
首先枚举没有放进盒子的巧克力中,长度最短的是哪块。
也就是说,盒子里的任一个间隔,都不可能大于这块巧克力的长度,且至少有一个间隔的长度严格小于它。
这样你从每个间隔里分出一点点到最短的那个间隔里,就可以保证每个间隔都放不下剩下的那些巧克力了。
既然枚举的是没有放进盒子的巧克力中最短的是那块,那么比它的短的巧克力就必须全部在盒子里。
除此之外,如果巧克力之间的间隔还是太大,就要从剩下的巧克力中再放一些进去。做个背包就可以了。
也就是说从剩下的巧克力中选取尽量少的,使得巧克力间的间隔达到要求,当然还有一个前提是这些巧克力有足够的空间能被放进去。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <climits>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
const int MAXN = 50;
const int MAXM = 1100;
int a[MAXN];
int d[MAXM];
int main()
{
int cas;
scanf("%d", &cas);
for (int T =1; T <= cas; T ++)
{
int n, l;
scanf("%d %d", &l, &n);
for (int i = 0; i < n; i ++)
{
scanf("%d", &a[i]);
}
sort(a, a + n);
int ans = n;
int tmp = 0;
for (int i = 0; i < n; i ++)
{
int ret = tmp + (i + 1) * a[i];
memset(d, -1, sizeof(d));
d[0] = 0;
for (int j = i; j < n; j ++)
{
for (int k = 1000 - a[j]; k >= 0; k --)
{
if (d[k] != -1)
{
d[k + a[j]] = (d[k + a[j]] == -1) ? d[k] + 1 : min(d[k+a[j]], d[k] + 1);
}
}
}
for (int j = 0; j <= 1000; j ++)
{
if (d[j] != -1)
{
if (j + tmp <= l && d[j] * a[i] + j + ret > l)
{
ans = min(ans, i + d[j]);
}
}
}
tmp += a[i];
}
printf("%d\n",ans);
}
return 0;
}