小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下,请问有多少种组成歌单的方法。
解法一(参考自牛客网ID为 我是牛我是牛牛 的代码(带有笔者自己写的解析)):
看作是01背包问题
#include<iostream>
using namespace std;
int B[201][1001]={0}; // B[i][j],歌单剩余长度为j,用来取1-i首歌的最多方案数
int w[201]; //w[i] :第i首歌占用的长度
int main(){
int k,a,x,b,y,i,j;
while(cin>>k){
cin>>a>>x>>b>>y;
for(i=0;i<=x+y;i++){
B[i][0]=1; //B[i][0]都为1,意思是只要歌单长度为0,就算是1种方案。
}
for(i=1;i<=x;i++){
w[i]=a;
}
for(i=x+1;i<=x+y;i++ ){
w[i]=b;
}
for(i=1;i<=x+y;i++){
for(j=1;j<=k;j++){
/* 当当前所剩的长度>=歌曲i的长度时(忽略掉%1000000007)
(当有i首歌 剩余长度为j 的方案总数)=不取这首歌的(即有i-1首歌 剩余长度为j的方案总数)+ 取这首歌(即有i-1首歌 剩余长度为j-这首歌长度p[i]的方案总数)
否则(这首歌的长度已经超过歌单剩余长度了)
(当有i首歌 剩余长度为j 的方案总数)=不取这首歌的(即有i-1首歌 剩余长度为j的方案总数) */
if(j>=w[i])
B[i][j]=(B[i-1][j-w[i]]%1000000007+B[i-1][j]%1000000007)%1000000007;
else
B[i][j]=B[i-1][j];
}
}
cout<<B[x+y][k]<<endl; //B[x+y][k]就是当歌单长度为k,有x+y首歌时的最多方案数
}
}
————————————————
原文链接:https://blog.csdn.net/jmasker/article/details/86842035