题目描述
Y手上有n盒积木,每个积木有个重量。现在他想从每盒积木中拿一块积木,放在一起,这一堆积木的重量为每块积木的重量和。现在他想知道重量和最小的k种取法的重量分别是多少。(只要任意更换一块积木,就视为一种不同的取法。如果多种取法重量总和一样,我们需要输出多次。)
【题目分析】
分组背包。
【代码】
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int f[101][10001];
int a[101][101];
int n,k,x,v;
int read()
{
int ret=0,f=1;
char ch=getchar();
while (ch>'9'||ch<'0'){if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){ret*=10;ret+=ch-'0';ch=getchar();}
return ret*f;
}
int main()
{
f[0][0]=1;
n=read();k=read();int uppe=0;
for (int i=1;i<=n;++i)
{
x=a[i][0]=read();int tmp=0;
while (x)
{
a[i][x]=read();
tmp=max(tmp,a[i][x]);
x--;
}
uppe+=tmp;
}
// printf("uppe is %d\n",uppe);
for (int i=1;i<=n;++i)
for (int j=1;j<=a[i][0];++j)
{
// printf("%d %d\n",i,j);
for (int k=uppe;k>=a[i][j];--k)
if (f[i-1][k-a[i][j]]) f[i][k]+=f[i-1][k-a[i][j]];
}
int i=1;
while (k)
{
int tmp=min(f[n][i],k);
for (int j=1;j<=tmp;--k,++j)
printf("%d%c",i,k==1?'\n':' ');
i++;
}
}