Input
第一行为两个用空格隔开的正整数v和T。表示背包的空间和物品的组数。接下来有T行,每行先是一个正整数ni,表示这组物品有ni个,然后ni个正整数,表示每个物品的大小。
Output
仅一个数,表示剩余空间的最小值。
Sample Input
100 3
3 7 6 8
2 80 70
4 101 108 103 150
Sample Output
6
Data Constraint
Hint
【样例说明】
第1组选6、8,第2组选80,第3组不选。
【限制】
60%的数据满足:1 <= ni <= 10
100%的数据满足:1 <= ni <= 100,1<=v<=5000,1<=T<=10
做法:预处理所有的可能取的值,那不就是01背包了嘛
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define N 6007
#define ni 107
#define ll long long
using namespace std;
bool f[20][N];
int a[ni], s[12];
int n, m;
ll d[12][ni * ni], z[ni * ni];
int min(int a, int b){ return a < b ? a : b; }
int main()
{
scanf("%d%d", &m, &n);
rep(i, 1, n)
{
int t;
memset(a, 0, sizeof(a));
memset(z, 0, sizeof(z));
scanf("%d", &t);
rep(j, 1, t)
scanf("%d", &a[j]);
int tot = 0;
rep(j, 1, t)
{
z[++tot] = a[j];
rep(k, j + 1, t)
if (j < t) z[++tot] = z[tot - 1] + a[k];
++tot;
}
sort(z + 1, z + tot + 1);
rep(j, t + 1, tot)
d[i][j - t] = z[j];
s[i] = tot - t;
}
f[0][0] = 1;
rep(i, 1, n)
rep(j, 0, s[i])
{
if (d[i][j] > m) break;
rep(k, 0, m - d[i][j])
if (f[i - 1][k]) f[i][k + d[i][j]] = 1;
}
int ans = 0;
rep(i, 0, m)
if (f[n][i]) ans = m - i;
printf("%d", ans);
}