洛谷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 }