您的位置:首页 > 其它

洛谷 P2409 小Y的积木 (dp)

2016-10-30 16:43 267 查看


小Y的积木


题目背景

Y是个大建筑师,他总能用最简单的积木拼出最有创意的造型。


题目描述

Y手上有n盒积木,每个积木有个重量。现在他想从每盒积木中拿一块积木,放在一起,这一堆积木的重量为每块积木的重量和。现在他想知道重量和最小的k种取法的重量分别是多少。(只要任意更换一块积木,就视为一种不同的取法。如果多种取法重量总和一样,我们需要输出多次。)


输入输出格式

输入格式:

第一行输入两个整数,n,k,意义如题目所描述。

每组数据接下来的n行,第一个整数为mi,表示第i盒积木的数量,在同一行有mi个整数,分别表示每个积木的重量。

输出格式:

一行,重量最小的k种取法的重量,要求对于每个数据,从小到大输出


输入输出样例

输入样例#1:
3 10
4 1 3 4 5
3 1 7 9
4 1 2 3 5


输出样例#1:
3 4 5 5 6 6 7 7 7 7













说明

对于30%的数据:2<=mi<=10,1<=n<=10

对于50%的数据:2<=mi<=50,1<=n<=50

对于100%的数据:2<=mi<=100,1<=n<=100,1<=k<=10000,每个积木的重量为不超过100的正整数,所有mi的积大于等于k。本题不卡常。
题解:dp

f[i][j] 表示选取到第i盒,总值为j的方案数。

从小到大枚举j,有多少方案就输出几个,找到输出k个为止。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 103
using namespace std;
int block

,n,m,maxn;
int f
[N*N];
int main()
{
freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&block[i][0]);
for (int j=1;j<=block[i][0];j++)
scanf("%d",&block[i][j]);
sort(block[i]+1,block[i]+block[i][0]+1);
maxn+=block[i][block[i][0]];
}
f[0][0]=1;
for (int i=1;i<=n;i++)
for (int k=1;k<=maxn;k++)
for (int j=1;j<=block[i][0];j++)
if (k-block[i][j]>=0)
f[i][k]+=f[i-1][k-block[i][j]];
int sum=0; int now=1;
while (true) {
bool pd=false;
for (int i=1;i<=f
[now];i++){
printf("%d ",now); sum++;
if (sum==m) {  pd=true;  break;}
}
now++;
if (pd) break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: