中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++動態規劃中關于背包問題怎么解決

發布時間:2023-03-15 11:56:07 來源:億速云 閱讀:102 作者:iii 欄目:開發技術

本篇內容主要講解“C++動態規劃中關于背包問題怎么解決”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++動態規劃中關于背包問題怎么解決”吧!

一、分割等和子集-最后一塊石頭的重量II

背包問題,難點往往在第一步:dp數組表示什么

分割等和子集問題,較好的方式是:求裝滿背包后最大重量是多少(有點繞哈哈)

這是個題型:對于判斷能不能恰好裝滿背包的問題,用dp表示重量,判斷是否最終的dp[m]==m

bool canPartition(int* nums, int numsSize){
    //首先數組元素求和的sum,若sum%2==1,返回false
    //若sum%2==0,定義m=sum/2,n=numsSize
    //則問題變成了能否裝滿容量為m的背包
    //進一步變成了求裝滿容量為m的背包得到的最大價值量(本題價值量即為重量)
    //1.dp[j]表示裝滿容量為j的背包能獲得的最大價值量
    //2.遞推式:dp[j]=fmax(dp[j],dp[j-nums[i]]+nums[i]);
    //3.dp數組初始化:dp[i]=0;
    //4.遍歷順序:0-1背包順序(滾動數組)
    int sum=0;
    for(int i=0;i<numsSize;i++) sum+=nums[i];
    if(sum%2==1) return false;
    int m=sum/2,n=numsSize;
    int dp[m+1];
    for(int j=0;j<=m;j++) dp[j]=0;
    for(int i=0;i<n;i++){
        for(int j=m;j>=nums[i];j--)
            dp[j]=fmax(dp[j],dp[j-nums[i]]+nums[i]);
    }
    if(dp[m]==m) return true;
    else return false;
}

二、目標和

求組合數模板:dp[0]=1;dp[j]+=dp[j-nums[i]];

int findTargetSumWays(int* nums, int numsSize, int target){
    //首先數組元素求和的sum,若滿足題意,m+(m-target)=sum
    //若(sum+target)%2==1,返回0;
    //若sum<abs(target),返回0;
    //否則,有m=(sum+target)/2;
    //問題就變成了整數m可以有多少表達式表示出
    //進一步變成了求裝滿容量為m的背包的最大組合數
    //1.dp[j]表示裝滿容量為j的背包的最大表達式的組合數
    //2.遞推式:
    //組合問題模板:dp[0]=1;dp[j]+=dp[j-nums[i]];
    //3.dp數組初始化:dp[i]=0;dp[0]=1;
    int sum=0;
    for(int i=0;i<numsSize;i++) sum+=nums[i];
    if(sum<abs(target)||(sum+target)%2==1) return 0;
    int m=(sum+target)/2,n=numsSize;
    int dp[m+1];
    for(int i=1;i<=m;i++) dp[i]=0;
    dp[0]=1;
    for(int i=0;i<n;i++){
        for(int j=m;j>=nums[i];j--)
            dp[j]+=dp[j-nums[i]];
    }
    return dp[m];
}

三、一和零

注意二維滾動數組不能寫在同一個for循環中,這題背一下

int findMaxForm(char ** strs, int strsSize, int m, int n){
    //本題是二維背包,不過是比一維多了一步而已
    //1.dp[i][j]表示背包容量為i個0、j個1時,最多能裝的物品個數
    //2.遞推式:
    //dp[i][j]=fmax(dp[i][j],dp[i-cnt0][j-cnt1]+1);
    //3.dp數組初始化:
    //dp[i][j]=0;
    //4.遍歷順序:二維滾動數組(注意不能把i和j寫在同一個for循環中)
    int dp[m+1][n+1];
    for(int i=0;i<=m;i++){
        for(int j=0;j<=n;j++)
            dp[i][j]=0;
    }
    for(int k=0;k<strsSize;k++){
        int cnt0=0,cnt1=0;
        int len=strlen(strs[k]);
        for(int i=0;i<len;i++){
            if(strs[k][i]=='0') cnt0++;
            else cnt1++;
        }
        for(int i=m;i>=cnt0;i--){
            for(int j=n;j>=cnt1;j--){
                dp[i][j]=fmax(dp[i][j],dp[i-cnt0][j-cnt1]+1);
            }
        }
    }
    return dp[m][n];
}

四、零錢兌換II

多重背包和0-1背包唯一的區別在遍歷順序

我們知道01背包內嵌的循環是從大到小遍歷,為了保證每個物品僅被添加一次。

而完全背包的物品是可以添加多次的,所以要從小到大去遍歷

int change(int amount, int* coins, int coinsSize){
    int m=amount,n=coinsSize;
    int dp[m+1];
    for(int i=1;i<=m;i++) dp[i]=0;
    dp[0]=1;
    for(int i=0;i<n;i++){
        for(int j=coins[i];j<=m;j++)
            dp[j]+=dp[j-coins[i]];
    }
    return dp[m];
}

五、排列與組合

組合總數IV(排列問題)

本題要求的是排列數(即考慮排列順序)

求排列數,外層遍歷重量,內層遍歷物品,且均為從左到右遍歷

int combinationSum4(int *nums,int n,int m){
    //1.dp[j]表示背包容量為j時,有多少種方法能使背包被裝滿“
    //2.遞推式:
    //dp[j]+=dp[j-nums[i]];
    //3.初始化:
    //dp[i]=0;dp[0]=1;
    //4.遍歷順序:
    //本題要求的是排列數(即考慮排列順序)
    //求排列數,外層遍歷重量,內層遍歷物品,且均為從左到右遍歷
    int dp[m+1];
    for(int i=1;i<=m;i++) dp[i]=0;
    dp[0]=1;
    for(int j=0;j<=m;j++){
        for(int i=0;i<n;i++){
            if(j>=nums[i]&&dp[j]<INT_MAX-dp[j-nums[i]])
                dp[j]+=dp[j-nums[i]];
        }
    }
    return dp[m];
}

零錢兌換(組合問題)

本題要求的是組合數(即不考慮排列順序)

求組合數,外層遍歷物品,內層遍歷重量,且均為從左到右遍歷

int int coinChange(int* coins, int coinsSize, int amount){
    //1.dp[j]表示背包容量為j時,有多少種方法能使背包被裝滿“
    //2.遞推式:
    //dp[j]+=dp[j-coins[i]];
    //3.初始化:
    //dp[i]=0;dp[0]=1;
    //4.遍歷順序:
    //本題要求的是組合數(即不考慮排列順序)
    //求組合數,外層遍歷物品,內層遍歷重量,且均為從左到右遍歷
    int m=amount,n=coinsSize;
    int dp[m+1];
    for(int i=1;i<=m;i++) dp[i]=0;
    dp[0]=1;
    for(int i=0;i<n;i++){
        for(int j=coins[i];j<=m;j++)
            dp[j]+=dp[j-coins[i]];
    }
    return dp[m];
}

到此,相信大家對“C++動態規劃中關于背包問題怎么解決”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

项城市| 察雅县| 晴隆县| 沁水县| 楚雄市| 台中市| 鹤山市| 盘山县| 德安县| 福清市| 靖江市| 涞源县| 宝兴县| 洱源县| 四会市| 高邑县| 潼关县| 民和| 抚松县| 合山市| 澎湖县| 灵宝市| 务川| 石楼县| 建始县| 博罗县| 鄯善县| 姚安县| 婺源县| 牙克石市| 长泰县| 连城县| 莆田市| 惠来县| 灵川县| 咸丰县| 白城市| 兰考县| 香河县| 江华| 弥勒县|