西北大学第四届程序设计竞赛新生赛(同步赛)(J)

链接: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;
}

猜你喜欢

转载自blog.csdn.net/wxl7777/article/details/85238479
今日推荐