链接:https://ac.nowcoder.com/acm/contest/321/J
来源:牛客网
众所周知,八意永琳擅长制作药物.
今天八意永琳又制作了很多份药物,但是由于材料组成的不同,最终的品级也会不同
已知八意永琳制作的药物中,一共有n种不同的主材料,用1...n编号,每种主材料有ai种产地,每种产地都有自己的品级.
每种主材料只取某个产地的一份,最终该药物的品级为所有主材料的品级之和.
她的弟子铃仙很好奇,可能的药物品级,到底有少种?
被称为"狂链接:https://ac.nowcoder.com/acm/contest/321/J
来源:牛客网
输入描述:
输入第一行包括一个整数n 接下来n行,每行一个数字ai,表示该种主材料的产地数量 紧接着是ai个整数kj,表示不同产地的材料品级 1<=n<=100 , 1<=ai<=10000,1<=ki<=300
输出描述:
输出一个整数,表示可能的种类数量
气之月兔"的铃仙实在算不出来了,你能帮帮她吗?
示例1
输入
5 1 1 1 1 2 1 2 3 1 2 3 1 100
输出
4
思路:这道题一眼看着是dp,但我在考虑复杂度的时候,有个地方处理不得用3重循环很容易想到,但如果你是按个数来的话肯定会超复杂度,但题目给的k很小这意味着在a个里面有重复,所以我以k来dp就好,类似分组背包.
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
const int maxn=3e4+100;
const int maxm=110;
int dp[maxm][maxn];
int st[maxm][350];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
for(int j=1;j<=a;j++)
{
int k;
scanf("%d",&k);
st[i][k]=1;
}
}
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=300;j++)
{
for(int l=0;l<=i*300;l++)
{
if(st[i][j]&&dp[i-1][l])
{
dp[i][j+l]=1;
}
}
}
}
int ans=0;
for(int i=1;i<=maxn;i++)
{
ans+=dp[n][i];
}
printf("%d\n",ans);
return 0;
}