Leetcode 879 盈利計劃 (動態規劃解法 c++)

題目描述:

幫派裏有 G 名成員,他們可能犯下各種各樣的罪行。第 i 種犯罪會產生 profit[i] 的利潤,它要求 group[i] 名成員共同參與。讓我們把這些犯罪的任何子集稱爲盈利計劃,該計劃至少產生 P 的利潤。有多少種方案可以選擇?因爲答案很大,所以返回它模 10^9 + 7 的值。

設dp[i][j][k]的含義爲前i個犯罪花費k個人達到至少j利潤的方案數,則有選做第i個犯罪還是不選:

dp[i][j][k] = dp[i-1][j][k] + dp[i-1][j-profit[i-1]][k-group[i-1]]

含義是不做第i個犯罪,那麼有dp[i-1][j][k]個方案;做第i個犯罪,有dp[i-1][j-profit[i-1]][k-group[i-1]]個方案。注意group和profit都是從下標0開始,所以爲i-1。

動態規劃很重要的一點是邊界問題。當利潤爲0時,無論i和k爲多少,dp[i][0][k]=1,表示只有一種方案(就是不做)。

代碼:

class Solution {
public:
    int profitableSchemes(int G, int P, vector<int>& group, vector<int>& profit) {
        const long Mod = 1e9 + 7;
        int T = group.size();
        vector<vector<vector<int>>> dp(T+1,vector<vector<int>>(P+1,vector<int>(G+1,0)));
        // dp[0][0][0] = 1;
        for (int i = 0;i<=T;i++){
            for(int j = 0;j<=G;j++){
                dp[i][0][j] = 1;
            }
        }
        for (int t = 1;t<=T;++t){
            int p = profit[t-1];
            int g = group[t-1];
            for(int i = 0;i<=P;++i){
                for (int j = 0; j<=G;++j){
                    dp[t][i][j] = (dp[t-1][i][j] + (j<g ? 0: dp[t-1][max(0,i-p)][j-g]))%Mod;
                }
            }
        }
        return dp[T][P][G];
    }
};

還有一些小細節需要注意,判斷利潤是否大於0,以及花費的人數是否大於第t個任務所需的人數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章