day-42 コードカプリスアルゴリズム合宿ダイナミックプランニングその4

416. 等和サブセットの分割

分析: 合計を 2 つの半分に分割する必要がありますが、合計の半分を満たすことができるサブセットが存在します。
アイデア:
  • 1.dp storage: 容量がj、dp[j]の場合にロードされる最大値
  • 2.dp[j]=max(dp[j],dp[j-nums[i]]+nums[i])  
  • 3. すべて0に初期化
  • 4. 走査順序: 外側の層で要素を走査し、内側の層で重みを走査します。

2: dp[j] は前のラウンドの最大合計であり、現在の nums[i] にまだ到達していないため、nums[j] をインストールしないことと同等です。

        dp[j-nums[i]]、なぜ j-nums[i] の容量が必要なのでしょうか? 容量は j でなければならないため、ロードする前に、容量 j-nums[i] の最大合計を見つける必要があります。 ] を実行し、現在の nums[i] をロードすると、総容量は j になります (dp[j]+nums[i] を直接使用すると、容量は j を超えます)。

1049.最後の石の重さ||

分析: 石が衝突したとき、残りの部分は、最も近い 2 つの石の山に相当します。
アイデア:
  • 1. dp ストレージ: まず石の合計を求め、その半分を見つけます。dp は、容量 j のデバイスの最大重量を保存します。
  • 2.dp[j]=max(dp[j],dp[j-stones[i]]-stones[i]);
  • 3. 初期化:すべて0に初期化
  • 4. トラバース順序: 外層の石をトラバースし、内層のトラバース容量
class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int total=0;
        for(auto it:stones) total+=it;
        int target=total/2;
        
        vector<int>dp(total+1,0);
        for(int i=0;i<stones.size();i++){
            for(int j=target;j>=stones[i];j--){
                dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return total-dp[target]*2;//装入的最大重量跟剩下的相抵消,剩余的就是最后一块石头
    }
};

494. ゴールと(一スワイプで刑務所に行く)

分析: 正の数の合計 - 負の数の合計 = 目標の合計 -> 正の数の合計 = (目標の合計 + 合計)/2
アイデア:
  • 1.dp ストレージ: 合計 (容量) が j の場合、dp[j] 中ロード方式があります。
  • 2.dp[ j ] =dp [ j - 数値 [ i ] ] ;
  • 3. 初期化: dp [0] =1;
  • 4. 走査順序: 外側の層で配列を走査し、内側の層で容量を走査します。
class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0;
        for(int it:nums) sum+=it;
        if(abs(target)>sum) return 0;//当总和小于目标和的绝对值时,不可能有情况(因为target被抵消过)
        //add表示正数的总和,sub表示负数的总和
        //add-(sum-add)=target
        //add=(target+sum)/2
        if((target+sum)%2==1) return 0;

        int bagSize=(target+sum)/2;
        vector<int> dp(bagSize+1,0);
        dp[0]=1;
        for(int i=0;i<nums.size();i++){
            for(int j=bagSize;j>=nums[i];j--)
                dp[j]+=dp[j-nums[i]];
        }
        return dp[bagSize];
    }
};

474. 1と0(投獄)

分析: この質問は依然としてバックパックに関するものですが、違いは 0 と 1 の 2 つの次元があることです。
アイデア:
  • 1.dp ストレージ: 0 の容量を i、1 の容量を j とすると、dp [ i ] [ j ] までの文字列を格納できます。
  • 2.dp [ j ]:dp [ i ] [ j ] =max( dp [ i ] [ j ] , dp [ i - zeroNum ][ j - oneNum ] + 1 ] 
  • 3. 初期化:すべて0に初期化
  • 4. 走査順序: 外側の層は文字列配列を走査し、内側の層は 2 つのループ走査を実行します。
class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>>dp(m+1,vector<int>(n+1,0));
        for(string str:strs){
            int oneNum=0,zeroNum=0;
            for(char c:str){
                if(c=='0') zeroNum++;
                else oneNum++;
            }
            for(int i=m;i>=zeroNum;i--){
                for(int j=n;j>=oneNum;j--){
                    dp[i][j]=max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
                }
            }
        }
        return dp[m][n];
    }
};

おすすめ

転載: blog.csdn.net/Ricardo_XIAOHAO/article/details/132685066