洛谷P2409 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。本题不卡常。

总和不超过10000,分组背包DP,看数值x可以被组合出几次,然后从小到大输出k个可以被组合出的次数即可

 1 /*By SilverN*/
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 #define LL long long
 8 using namespace std;
 9 const int mxn=101;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
13     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
14     return x*f;
15 }
16 int n,k;
17 int m[mxn];
18 int a[mxn][mxn];
19 int f[mxn][mxn*mxn];
20 int smm[mxn];
21 int main(){
22     n=read();k=read();
23     int i,j;
24     int mx=0;
25     for(i=1;i<=n;++i){
26         mx=0;
27         m[i]=read();
28         for(j=1;j<=m[i];++j){
29             a[i][j]=read();
30             if(a[i][j]>mx)mx=a[i][j];
31         }
32         sort(a[i]+1,a[i]+m[i]+1);
33         smm[i]=smm[i-1]+mx;
34     }
35     f[0][0]=1;
36     for(i=1;i<=n;++i){
37         for(j=smm[i];j;--j){
38             for(int l=1;l<=m[i];++l){
39                 if(a[i][l]>j)break;
40                 f[i][j]+=f[i-1][j-a[i][l]];
41             }
42         }
43     }
44     for(i=1;i<=smm[n];++i){
45         while(f[n][i] && k){
46             --f[n][i];--k;
47             printf("%d ",i);
48         }
49     }
50     return 0;
51 }
时间: 2024-08-08 20:06:16

洛谷P2409 Y的积木的相关文章

洛谷P2409 Y的积木 分组背包

P2409 Y的积木 题目背景 Y是个大建筑师,他总能用最简单的积木拼出最有创意的造型. 题目描述 Y手上有n盒积木,每个积木有个重量.现在他想从每盒积木中拿一块积木,放在一起,这一堆积木的重量为每块积木的重量和.现在他想知道重量和最小的k种取法的重量分别是多少.(只要任意更换一块积木,就视为一种不同的取法.如果多种取法重量总和一样,我们需要输出多次.) 输入输出格式 输入格式: 第一行输入两个整数,n,k,意义如题目所描述. 每组数据接下来的n行,第一个整数为mi,表示第i盒积木的数量,在同一

【洛谷P2409】Y的积木

这是一道dp-- f [ i ] [ j ] 表示前 i 组,总和为 j 时的方案数 f [ i ] [ j + a [ i ] [ k ] ] <-- f [ i - 1 ] [ j ] 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=105,M=11000; 6 int f[N][M],a[N][N],maxl[N

洛谷10月月赛Round.3

Rank11:260=60+100+100 P2409 Y的积木 题目背景 Y是个大建筑师,他总能用最简单的积木拼出最有创意的造型. 题目描述 Y手上有n盒积木,每个积木有个重量.现在他想从每盒积木中拿一块积木,放在一起,这一堆积木的重量为每块积木的重量和.现在他想知道重量和最小的k种取法的重量分别是多少.(只要任意更换一块积木,就视为一种不同的取法.如果多种取法重量总和一样,我们需要输出多次.) 输入输出格式 输入格式: 第一行输入两个整数,n,k,意义如题目所描述. 每组数据接下来的n行,第

洛谷P1969 积木大赛 贪心 差分

洛谷P1969 积木大赛 贪心 考虑差分 对区间 [l,r]+1 在差分数组上相当于 d[ l ]++ ; d[ r+1 ]-- ; 那么你得到原数组的差分数组后 当d[ i ] = x 则你需要 对 以 i 为左端点 右端点未知的一个区间加x次且这x加的可能不是同一个区间 所以最后只要将差分数组中所有正数加上去就行了 同样其实也可以用负数算的,但是负数算的话,要加上 d[ n+1 ] 即 a[ n+1 ] - a[ n ] 或者另一种思路对于一段上升(不下降)区间,我们在搭最高层时可以把下面一

洛谷P1969 积木大赛 数学

洛谷P1969 积木大赛 题意: 对于n个积木 排成了一排 高度不同 每次可以使 L--R的区间积木减一,但不能使积木高度减至 0 以下 , 求几次能够使得所有积木高度降为 0 数学 1.对于一段 上升.不下降序列,其较低的一定会在解决最高时候就解决掉 2.而这段区间还同时会解决掉下一段区间最小值 以下的那些积木 3.所以这段区间消耗值就是这段上升(不下降)序列的最大值减最小值 先写思路:对于一段上升(不下降)区间,我们在搭最高层时可以把下面一起搭了而如果这个区间开始下降,那么我们进入另一个区间

BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze do?y

[题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最大值. 枚举右端点,如果左端点到右端点的元素和减去区间内长为d的子序列中元素和的最大值,大于给定的P,那么就把左端点向右挪. #include<cstdio> #include<algorithm> #define N 2000010 #define rg register #defi

洛谷1231 教辅的组成

洛谷1231 教辅的组成 https://www.luogu.org/problem/show?pid=1231 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题.然而出现在他眼前的书多得数不胜数,其中有书,有答案,有练习册.已知一个完整的书册均应该包含且仅包含一本书.一本练习册和一份答案,然而现在全都乱做了一团.许多书上面的字迹都已经模糊了,然而HansBug还是可

洛谷教主花园dp

洛谷-教主的花园-动态规划 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的

洛谷 P3367 并查集模板

#include<cstdio> using namespace std; int n,m,p; int father[2000001]; int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void unionn(int i,int j) { father[j]=i; } int main() { scanf("%d%d",&n,&m); for