洛谷 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; } }
相关文章推荐
- 【洛谷 P2409】Y的积木(dp(01背包))
- 洛谷 P2409 Y的积木
- 洛谷 P2409 Y的积木
- 洛谷P2409 Y的积木
- 动态规划入门 洛谷P2409 Y的积木
- 洛谷 P2409 Y的积木
- DP 洛谷 P1280 尼克的任务
- 【DP】洛谷 P1470 最长前缀 Longest Prefix
- 洛谷 P1969 积木大赛
- 洛谷.1782.旅行商的背包(背包DP 单调队列)
- 洛谷P1060 开心的金明(DP,0-1背包)
- 洛谷 1063 dp 区间dp
- BZOJ 1413 [ZJOI2009] [洛谷2599] 取石子游戏 (博弈论 dp )
- 洛谷 2285 打鼹鼠 递推? DP? 解题报告
- 尼克的任务 dp 洛谷1280
- 尼克的任务 dp 洛谷1280
- 洛谷1417 烹调方案 dp 贪心
- 洛谷 2409 dp 月赛题目
- 洛谷 1063 dp 区间dp
- 洛谷 2409 dp 月赛题目