最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++動態(tài)規(guī)劃中關于背包問題講解

 更新時間:2023年03月15日 10:03:39   作者:清風何渡  
可能有些讀者有接觸過動態(tài)規(guī)劃,可能也有一些讀者以前完全不知道動態(tài)規(guī)劃這個東西,別擔心,我這篇文章會為讀者做一個入門,好讓讀者掌握這個重要的知識點

一、分割等和子集-最后一塊石頭的重量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循環(huán)中,這題背一下

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循環(huán)中)
    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背包唯一的區(qū)別在遍歷順序

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

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

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++動態(tài)規(guī)劃中關于背包問題講解的文章就介紹到這了,更多相關C++動態(tài)規(guī)劃背包內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++實現的O(n)復雜度內查找第K大數算法示例

    C++實現的O(n)復雜度內查找第K大數算法示例

    這篇文章主要介紹了C++實現的O(n)復雜度內查找第K大數算法,結合實例形式分析了算法的原理以及具體實現方法,需要的朋友可以參考下
    2017-08-08
  • C++的缺省參數你了解嘛

    C++的缺省參數你了解嘛

    這篇文章主要為大家介紹了C++缺省參數,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • C++中圖片類型的識別與轉換詳解方法

    C++中圖片類型的識別與轉換詳解方法

    本文簡單的介紹一下C++語言中如何識別圖片文件的類型,以及各圖片類型之間的轉換方法,并提供相關的源碼供大家參考,感興趣的朋友快來看看吧
    2021-11-11
  • C語言 冒泡排序算法詳解及實例

    C語言 冒泡排序算法詳解及實例

    這篇文章主要介紹了C語言 冒泡排序算法詳解及實例的相關資料,需要的朋友可以參考下
    2016-11-11
  • C語言預處理器使用方法講解

    C語言預處理器使用方法講解

    C預處理器不是編譯器的組成部分,但是它是編譯過程中一個單獨的步驟。簡言之,C預處理器只不過是一個文本替換工具而已,它們會指示編譯器在實際編譯之前完成所需的預處理。我們將把C預處理器(C Preprocessor)簡寫為CPP
    2022-12-12
  • c語言讀取csv文件和c++讀取csv文件示例分享

    c語言讀取csv文件和c++讀取csv文件示例分享

    這篇文章主要介紹了c語言讀取csv文件和c++讀取csv文件示例,需要的朋友可以參考下
    2014-03-03
  • 淺談 C++17 里的 Visitor 模式

    淺談 C++17 里的 Visitor 模式

    Visitor模式經常用于將更新的設計封裝在一個類中,并且由待更改的類提供一個接受接口,其關鍵技術在于雙分派技術,本文主要介紹 C++17 里的 Visitor 模式的相關資料,需要的朋友可以參考下面文章的具體內容
    2021-09-09
  • typedef和#define用法區(qū)別總結

    typedef和#define用法區(qū)別總結

    在C還是C++代碼中,typedef都使用的很多,在C代碼中尤其多,typedef與#define有些相似,其實是不同的,特別是在一些復雜的用法上,下面這篇文章主要給大家介紹了關于typedef和#define用法區(qū)別總結的相關資料,需要的朋友可以參考下
    2023-06-06
  • C++聯合體union用法實例詳解

    C++聯合體union用法實例詳解

    這篇文章主要介紹了C++聯合體union用法,較為詳細的分析了C++中聯合體的概念、實用技巧及相關注意事項,需要的朋友可以參考下
    2015-05-05
  • C++利用libcurl庫實現多線程文件下載

    C++利用libcurl庫實現多線程文件下載

    這篇文章主要為大家詳細介紹了C++如何利用libcurl庫實現多線程文件下載,文章的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-01-01

最新評論

临颍县| 天长市| 凉山| 鹿泉市| 开江县| 门源| 卢湾区| 德庆县| 攀枝花市| 姚安县| 顺昌县| 文安县| 左贡县| 当阳市| 梅河口市| 新宾| 顺平县| 遂宁市| 连南| 福贡县| 金寨县| 固安县| 二连浩特市| 拉孜县| 渭源县| 宜春市| 葵青区| 镇沅| 封开县| 潜江市| 卫辉市| 鄂州市| 分宜县| 黄陵县| 时尚| 康马县| 桂平市| 张家界市| 武山县| 红桥区| 沁源县|