洛谷P1077 摆花——题解

题目传送

题目大意:有按顺序放的n种花,相同种类的花放一起,每种花最多放ai盆,共放了m盆花,求放花方案数。

求方案个数一般有以下思路:1、搜索;2、递推/动态规划;3、贪心;4、分治。。。

玄学估计发现,仅是可行解就有非常多的数量,显然搜索不行了。联想到“背包问题的方案总数”,猛然发现:这题不就相当于每个物品的重量都为1,最多选ai个,求放满背包的方案总数吗?尝试写出状态:设dp[k][i]为只可能用前k种花、摆了i盆花的方案数,状态转移方程:(当i大于等于ak时)dp[k][i]=dp[k-1][i-0]+dp[k-1][i-1]+..+dp[k-1][i-ak];(当i小于ak时)dp[k][i]=dp[k-1][i-0]+dp[k-1][i-1]+..+dp[k-1][0]。注意边界条件:a[1][i]=1,i=0,1,...,a1,即只用第一种花摆花时是不能由上面的状态转移方程推出来的。

见AC代码:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 
 4 using namespace std;
 5 
 6 int a[101],n,m,dp[101][101],sum;
 7 
 8 const int mod=1000007;
 9 
10 int main()
11 {
12        scanf("%d%d",&n,&m);
13        for(int i=1;i<=n;i++)
14            scanf("%d",&a[i]);
15        for(int i=0;i<=a[1];i++) dp[1][i]=1;//初始化边界条件 
16        sum=a[1];
17        for(int k=2;k<=n;k++)//花的种类 
18        {
19            sum+=a[k];
20            for(int i=0;i<=sum&&i<=m;i++)//共要摆几个 
21            {
22                for(int j=0;j<=a[k]&&j<=i;j++)//第k种用几个 
23                    dp[k][i]+=dp[k-1][i-j];
24             dp[k][i]%=mod;
25         }
26     }
27     cout<<dp[n][m];
28     return 0;
29 }

 

posted @ 2019-06-17 15:22  千叶繁华  阅读(519)  评论(1编辑  收藏  举报