第三题 摆花
#include<bits/stdc++.h>
using namespace std;
int a[101],dp[101][101],x,y,z,m,n;
int main(){
cin>>n>>m;
dp[0][0]=1;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=a[i];j++)
for(int x=0;x<=m-j;x++)
{
dp[i][x+j]=(dp[i-1][x]+dp[i][x+j])%1000007;
}
cout<<dp[n][m];
return 0;
}
又是一道动规题,依然以前面状态最优推当前最优。
显然用i种花摆0个,不管怎么摆都只有一种方案。
这里我小小的偷懒用dp[0][0]=1;代替了
for(int i=0;i<=n;i++)
dp[i][0]=1;
根据
for(int i=1;i<=n;i++)
for(int j=0;j<=a[i];j++)
for(int x=0;x<=m-j;x++)
{
dp[i][x+j]=(dp[i-1][x]+dp[i][x+j])%1000007;
}
当x=0,j=0时dp[i][0]自然会被赋值为dp[i][0]=1。
dp[i][]跟前面的哪些状态有关呢。
dp[i][]表示当前状态下的最大方案数,那么它肯定等于能到达dp[i][]上一个状态的所有dp[i-1][]相加的和。如dp[i][q],
dp[i][q]=dp[i-1]+dp[j1+x1]+dp[j2+x2]......+dp[jn+xn]。jn+xn=q,jn表示这次又能摆多少盆花,xn表示在<=m-j的状态下,摆jn盆花就能达到q的那个数。所以
dp[i][x+j]+=dp[i-1][x];
举个例子,若最多摆4盆花,j又最多为3,dp[2][3]=dp[1][0]+dp[1][1]+dp[1][2]+dp[1][3],k=x+j,有多少个到达x的方案,就有多少个到达k的方案。因为x本身也在变化,而k恒定,所以k的方案即为所有到达x的方案数相加。哈,终于把自己说明白了。
但是要想使k恒定不便于编写,所以动规嘛,状态随时在改变。用x和j一次次的更新每一个k所代表的方案数的值。反正你每一层循环k最多只会涉及到一次。如当j恒定了,x从0到2,其中要么没有更新k,如3,4都没有被更新,要么这些k只会被更新一次,如1,2(前文条件,最多摆三盆花)。所以只有一个动规方程。
理顺了一点了。