HDU 6092Rikka with Subset

来源:互联网 发布:ubuntu core 图形界面 编辑:程序博客网 时间:2024/05/20 17:09

【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=6092

题目意思

T组测试,接下来一行n和m,下面一行m+1个数字代表B(0~m)求A序列,Bi 代表A序列中的所有子集之和为i的有Bi个,A序列总和为m,n个元素;

解题思路

一个0 1背包问题,有空子集等于1可以得出初始值dp【0】=1;然后根据b数组和为i个数-dp中由小数子加和为的个数得出a数组中数值为i的个数。

这题用到的0 1背包,而0 1背包更新都是从后往前的(必须后往前,不然会重复计算)。更新原则:出现一个i;那么dp【k】+=dp【k-i】(如出现了一个2,那么和为5的个数就要加上 和为3个数)

代码部分

#include<bits/stdc++.h>using namespace std;#define ll long longint main(){    int t;    scanf("%d",&t);    while (t--)    {        int a[10005],b[10005],dp[10005];///dp存储和为i的个数        memset(dp,0,sizeof(dp));        int top=0,n,m;        scanf("%d %d",&n,&m);        for (int i=0; i<=m; i++)            scanf("%d",&b[i]);        dp[0]=1;    ///初始化值        for (int i=1; i<=m; i++)        {            int s=b[i]-dp[i];    ///计算a中i的个数            for (int j=0; j<s; j++)    ///每次多个i都要更新一次背包            {                a[top++]=i;                for (int k=m; k>=i; k--)///01背包更新                    dp[k]+=dp[k-i];            }        }        for(int i = 0; i < n; i++)        {            if(i > 0) printf(" ");            printf("%d", a[i]);//输出A序列        }        printf("\n");    }    return 0;}
原创粉丝点击