链接:https://ac.nowcoder.com/acm/problem/204553
来源:牛客网
宝盒
题目描述
上天眷顾了牛牛,给牛牛n个宝盒。牛牛会从这n个箱子中各取一件宝物去当掉来换钱(每个箱子中有m 件宝物)。牛牛想知道他用不同的方法取宝物能当来的钱数量的前k小值,为了避免输出量过大只要输出前k小的累计和。
输入描述:
第一行一个整数n,k,表示宝箱个数以及前k小的可获得的价值,接下来n行每行开头一个整数mi 表示第一个宝箱中宝物个数,接下来mi个数表示每件宝物的价值wi
输出描述:
一行一个整数ans,前k小和。
示例1
输入
3 10
4 1 3 4 5
3 1 7 9
4 1 2 3 5
输出
57
说明
前10小分别为{3,4,5,5,6,6,7,7,7,7}3,4,5,5,6,6,7,7,7,7
//动态规划就可以了
//package 牛客赛;
import java.util.*;
public class Main {
public static int a[][]=new int [105][105*105];
public static int dp[][]=new int [105][105*105];//dp[i][j]表示前i组组成和为j的个数
public static int len[]=new int [105];
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
int n=sc.nextInt();
int k=sc.nextInt();
for(int i=1;i<=n;i++)
{
len[i]=sc.nextInt();
for(int j=1;j<=len[i];j++)
a[i][j]=sc.nextInt();
}
for(int i=1;i<=len[1];i++) dp[1][a[1][i]]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=len[i];j++)
{
for(int p=1;p<=10000;p++)
{
if(p+a[i][j]<=10000)
dp[i][p+a[i][j]]+=(dp[i-1][p]);
}
}
}
long ans=0;
for(int i=1;i<=10000;i++)//判断前k个
{
if(dp[n][i]!=0)
{
if(k-dp[n][i]>=0) {
ans+=(dp[n][i]*i);
k=k-dp[n][i];
}
else {
ans+=k*i;
k=0;
}
}
if(k==0)
break;
}
System.out.println(ans);
}
}