[編程題]小Q的歌單(動態規划)


鏈接:https://www.nowcoder.com/questionTerminal/f3ab6fe72af34b71a2fd1d83304cbbb3
來源:牛客網
問題描述:
小Q有X首長度為A的不同的歌和Y首長度為B的不同的歌,現在小Q想用這些歌組成一個總長度正好為K的歌單,每首歌最多只能在歌單中出現一次,在不考慮歌單內歌曲的先后順序的情況下,請問有多少種組成歌單的方法。 

輸入描述:

每個輸入包含一個測試用例。
每個測試用例的第一行包含一個整數,表示歌單的總長度K(1<=K<=1000)。
接下來的一行包含四個正整數,分別表示歌的第一種長度A(A<=10)和數量X(X<=100)以及歌的第二種長度B(B<=10)和數量Y(Y<=100)。保證A不等於B。

輸出描述:

輸出一個整數,表示組成歌單的方法取模。因為答案可能會很大,輸出對1000000007取模的結果。
示例1

輸入

5
2 3 3 3

輸出

9
解決思路:

1. 用數組dp來存儲結果,dp[i][j]表示用前j首歌表示長度為i的歌單的方法數,i=1…K,j=1,…,na+nb。na是第1種歌的數量,nb是第2種歌的數量 
2. lens[j]表示第j首歌的長度,如果i>=lens[j],那么由前j首歌組成長度為i的歌單的方法數可分為兩部分,第一部分是dp[i][j-1],即由前j-1首歌組成長度
為i的歌單的方法數,第二部分是dp[i-lens[j]][j-1],即由j-1首歌組成長度為i-lens[j]的歌單的方法數,因為第j首歌已經占據了lens[j]的長度。 
3. 如果i<lens[j]i<lens[j],那么dp[i][j][i][j]等於dp[i][j1][i][j−1]。
代碼:
#include <iostream>
#include <algorithm>
#include<string.h>
#include<map>
#include<iterator>
#include<math.h>
using namespace std;
const int mod =1000000007;
int k;
int a,x,b,y;
int dp[1010][210];
int len[210];
int main()
{
    cin>>k;
    cin>>a>>x>>b>>y;
    int length=x+y;
    memset(dp,0,sizeof(dp));
    memset(len,0,sizeof(len));
    dp[0][0]=1;
    for(int i=1;i<=x;i++)
        len[i]=a;
    for(int i=x+1;i<=length;i++)
        len[i]=b;
    for(int i=0;i<=k;i++)
        for(int j=1;j<=length;j++)
    {
        if(i>=len[j])
        {
            dp[i][j]=(dp[i][j-1]+dp[i-len[j]][j-1])%mod;
        }
        else
        {
            dp[i][j]=dp[i][j-1]%mod;
        }
    }
    cout<<dp[k][length]<<endl;
    return 0;
}

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM