题目大意:
一条长为n,宽为1的丝带,可以剪成多条小丝带(长度须为整数)。将这些丝带分配到一个宽为w,高为h的矩形框内(每条丝带占宽度为1),丝带可以不全用上,但不能出现所有丝带长度都相等的情况(包括0)。并且不能将1条丝带叠放到另一条丝带的上方,就是每个宽度只能放一条丝带。现在给出n,w,h,求出有多少种不同的组合。
题解:
一开始在往排列组合上想,推出如果n>=w*h,那么结果就是然后n<w*h的情况,本想用隔板法 ,但是这样的话就有可能某一段的长度大于h了......
后来看了dalao的博客才明白是dp......其实看到w,h的范围是100也多少有点dp的味道的
dp[i][j]代表前i个数,用的丝带总长度为j的方案数
复杂度为O(nwh)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define mod 1000000007
using namespace std;
ll dp[110][10010];
int main()
{
int n,w,h;
cin>>n>>w>>h;
dp[0][0]=1;
for(int i=1;i<=w; ++i)
for(int j=0; j<=n;++j)
for(int k=0;k<=h; ++k)
{
if(j+k>n)break;
dp[i][j+k]+=dp[i-1][j];//当前第i个位置应该放的丝带长度
if(dp[i][j+k]>mod)
dp[i][j+k]-=mod;
}
ll ans=0;
for(int i=0; i<=n; ++i)
{
ans+=dp[w][i];
if(ans>mod)ans-=mod;
}
if(n<w*h)
ans-=n/w+1;
else ans-=h+1;
ans=(ans+mod)%mod;
cout<<ans<<endl;
return 0;
}