国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

這篇具有很好參考價值的文章主要介紹了60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

簡單多狀態(tài)問題

文章目錄

  • 一.按摩師
  • 二.打家劫舍系列
  • 三.刪除并獲得點數(shù)
  • 四.粉刷房子

1.按摩師

力扣鏈接:力扣

一個有名的按摩師會收到源源不斷的預(yù)約請求,每個預(yù)約都可以選擇接或不接。在每次預(yù)約服務(wù)之間要有休息時間,因此她不能接受相鄰的預(yù)約。給定一個預(yù)約請求序列,替按摩師找到最優(yōu)的預(yù)約集合(總預(yù)約時間最長),返回總的分鐘數(shù)。

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

首先我們分析一下題目:1.每個預(yù)約可以選擇接或者不接 2.不能接受相鄰的預(yù)約。

1.狀態(tài)表示

我們用dp[i]表示i位置的最長分鐘數(shù),而i位置又可以分為兩種情況,一種是接,一種是不接,所以我們用兩個dp表來表示狀態(tài)。

f[i]表示接i位置的最長分鐘數(shù)

g[i]表示不接i位置的最長分鐘數(shù)?

2.狀態(tài)轉(zhuǎn)移方程

因為f[i]表示接i位置的預(yù)約,由于題目要求不能接受相鄰的預(yù)約,所以我們一定不能接受i-1位置的預(yù)約,而g[i-1]就表示不接i-1位置的最長分鐘數(shù),又因為我們接了i位置要加上i位置的分鐘數(shù),所以

f[i] = g[i-1] + nums[i];

g[i]表示不接i位置,那么我們可以選擇接受i-1位置或者不接受i-1位置,又因為我們要的是最大值,所以取這兩種情況的較大值即可。

g[i] = max(f[i-1],g[i-1])

3.初始化

從狀態(tài)轉(zhuǎn)移方程來看,我們造成越界的位置只有f[0]和g[0],而f[0]表示接受0位置的最長分鐘數(shù),那么f[0] = nums[0]? ? ?g[0] = 0.

4.填表

已知f[0]和g[0]所以從左向右依次填表,兩個表一起填

5.返回值

因為預(yù)約時長都是正數(shù),所以越到后面時間越長,那么最長的只有兩種情況:最后一個位置接或者最后一個位置不接,此題要求最大值,所以是這兩個情況的較大值。

class Solution {
public:
    int massage(vector<int>& nums) {
       if (nums.size()==0) return 0;
       //創(chuàng)建dp表
       int n = nums.size();
       vector<int> f(n,0),g(n,0);
       f[0] = nums[0],g[0] = 0;
       for (int i = 1;i<n;i++)
       {
           f[i] = g[i-1] + nums[i];
           g[i] = max(f[i-1],g[i-1]);
       }
       return max(f[n-1],g[n-1]);
    }
};

?注意:此題會有nums.size()為0的情況,所以需要單獨判斷。

2.打家劫舍系列

1.打家劫舍I

力扣鏈接:力扣

你是一個專業(yè)的小偷,計劃偷竊沿街的房屋。每間房內(nèi)都藏有一定的現(xiàn)金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統(tǒng),如果兩間相鄰的房屋在同一晚上被小偷闖入,系統(tǒng)會自動報警。

給定一個代表每個房屋存放金額的非負整數(shù)數(shù)組,計算你?不觸動警報裝置的情況下?,一夜之內(nèi)能夠偷竊到的最高金額。

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

?1.狀態(tài)表示

由于每個位置存在偷與不偷兩個狀態(tài),所以需要兩個表來表示。

f[i]表示偷i位置的最高金額

g[i]表示不偷i位置的最高金額

2.狀態(tài)轉(zhuǎn)移方程

f[i] = g[i-1] + nums[i];

g[i] = max(f[i-1],g[i-1])

3.初始化,4.填表,5.返回值

與第一題同理。

對于這個題我們應(yīng)該很熟悉吧,沒錯!和第一題按摩師簡直一模一樣,我們直接把按摩師的代碼復(fù)制過來:

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

?相同的代碼,立馬就搞定了,我們將這道題拿出來是為了引出打家劫舍II和III,所以并不是沒有用哦~

2.打家劫舍II

力扣鏈接:力扣

你是一個專業(yè)的小偷,計劃偷竊沿街的房屋,每間房內(nèi)都藏有一定的現(xiàn)金。這個地方所有的房屋都?圍成一圈?,這意味著第一個房屋和最后一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統(tǒng),如果兩間相鄰的房屋在同一晚上被小偷闖入,系統(tǒng)會自動報警?。

給定一個代表每個房屋存放金額的非負整數(shù)數(shù)組,計算你?在不觸動警報裝置的情況下?,今晚能夠偷竊到的最高金額。

注意:和I不同的是,這道題的前后是一個圈,也就是說這是一個環(huán)形問題,下面我們來解決這道題。

首先我們能將問題分為兩種情況,第一種是偷第一家的情況,第二種是不偷第一家的情況。

如果偷第一家,那么第二家和最后一家不能偷,也就是說我們只需要對2到n-2這個范圍做一次打家劫舍I,最后加上nums【0】即可。

如果不偷第一家,那么1到n-1這個范圍內(nèi)可以隨便偷,所以對1到n-1這個范圍內(nèi)做一次打家劫舍I即可。

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

class Solution {
public:
    int rob(vector<int>& nums) {
       int n = nums.size();
       return max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1));
    }
    int rob1(vector<int>& nums,int left,int right)
    {
        if (left>right) return 0;
        int n = nums.size();
        vector<int> f(n, 0), g(n, 0);
        f[left] = nums[left], g[left] = 0;
        for (int i = left+1; i <= right; i++)
        {
            f[i] = g[i - 1] + nums[i];
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[right], g[right]);
    }
};

?注意:當我們left大于right的時候那么一定是越界的情況,這種情況返回0即可。當我們將區(qū)間定為left到right這個閉區(qū)間,那么就從left+1開始填表,填到right,最后返回的時候也是返回dp表中right的位置,這里一定要畫圖映射位置關(guān)系。

3.刪除并獲得點數(shù)

力扣鏈接:力扣

給你一個整數(shù)數(shù)組?nums?,你可以對它進行一些操作。

每次操作中,選擇任意一個?nums[i]?,刪除它并獲得?nums[i]?的點數(shù)。之后,你必須刪除?所有?等于?nums[i] - 1?和?nums[i] + 1?的元素。

開始你擁有?0?個點數(shù)。返回你能通過這些操作獲得的最大點數(shù)。

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

?首先通過題目我們可以看到當我們刪除X獲取X的點數(shù)后,必須刪除X-1和X+1的元素,我們發(fā)現(xiàn)這與打家劫舍的問題非常像,都是不能獲得相鄰元素的值,那么我們該如何將這個問題轉(zhuǎn)化為打家劫舍問題呢?其實很簡單,因為X-1?和 X 和 X+1這三個數(shù)都是相鄰的,我們直接將nums映射到一個與下標同值的表中,比如3就放在下標為3的位置,并且給這個位置加上3,然后我們對這個新數(shù)組做一次打家劫舍就得到了最大點數(shù)。

比如實例2,映射后變成如下圖:

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

然后我們對這個數(shù)組做一次打家劫舍,獲取的最大點數(shù)就是9.

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        int hash[10001] = {0};
        const int n = 10001;
        for (auto& a:nums)
        {
            hash[a]+=a;
        }
        vector<int> f(n, 0), g(n, 0);
        for (int i = 1; i < n; i++)
        {
            f[i] = g[i - 1] + hash[i];
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[n-1], g[n-1]);
    }
};

?此方法就是用空間換時間。

4.粉刷房子

力扣鏈接:力扣

假如有一排房子,共?n?個,每個房子可以被粉刷成紅色、藍色或者綠色這三種顏色中的一種,你需要粉刷所有的房子并且使其相鄰的兩個房子顏色不能相同。

當然,因為市場上不同顏色油漆的價格不同,所以房子粉刷成不同顏色的花費成本也是不同的。每個房子粉刷成不同顏色的花費是以一個?n x 3?的正整數(shù)矩陣?costs?來表示的。

例如,costs[0][0]?表示第 0 號房子粉刷成紅色的成本花費;costs[1][2]?表示第 1 號房子粉刷成綠色的花費,以此類推。

請計算出粉刷完所有房子最少的花費成本。

60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講

?首先我們通過題目可以知道限制條件為:相鄰房屋不能涂成同一個顏色,下面我們開始解題。

1.狀態(tài)表示

dp【i】表示第i個房子所花費的最低成本,由于每個房子都可以涂成三種顏色,所以dp[i]又可以劃分成3個狀態(tài)。

dp[i][0]表示第i個房子涂成紅色的最低成本

dp[i][1]表示第i個房子涂成藍色的最低成本

dp[i][2]表示第i個房子涂成綠色的最低成本

2.狀態(tài)轉(zhuǎn)移方程

dp[i][0] = min(dp[i-1][1],dp[i-1][2]) + costs[i][0];

dp[i][1] = min(dp[i-1][0],dp[i-1][2]) + costs[i][1];

dp[i][2] = min(dp[i-1][0],dp[i-1][1]) + costs[i][2];

由于每個房子不能涂成相同顏色,所以第i層的房子如果是紅色,那么第i-1層就只能是藍色和綠色。

3.初始化

由于第一個房子不受前面任何房子的影響(i-1越界),所以第一個房子的三個狀態(tài)都是已知的

dp[0][0] = costs[0][0],

dp[0][1] = costs[0][1],

dp[0][2] = costs[0][2];

4.填表

從左向右依次填表,三個表一起填

5.返回值

返回最后一個房子的三種狀態(tài)的最小值。

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
       int n = costs.size();
       vector<vector<int>> dp(n,vector<int>(3));
       dp[0][0] = costs[0][0],dp[0][1] = costs[0][1],dp[0][2] = costs[0][2];
       for (int i = 1;i<n;i++)
       {
           dp[i][0] = min(dp[i-1][1],dp[i-1][2]) + costs[i][0];
           dp[i][1] = min(dp[i-1][0],dp[i-1][2]) + costs[i][1];
           dp[i][2] = min(dp[i-1][0],dp[i-1][1]) + costs[i][2];
       }
       int ret = dp[n-1][0];
       for (int i =1;i<3;i++)
       {
           if (dp[n-1][i]<ret)
           {
               ret = dp[n-1][i];
           }
       }
       return ret;
    }
};

當然我們也可以將最后取最小值的代碼簡化一下:

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
       int n = costs.size();
       vector<vector<int>> dp(n,vector<int>(3));
       dp[0][0] = costs[0][0],dp[0][1] = costs[0][1],dp[0][2] = costs[0][2];
       for (int i = 1;i<n;i++)
       {
           dp[i][0] = min(dp[i-1][1],dp[i-1][2]) + costs[i][0];
           dp[i][1] = min(dp[i-1][0],dp[i-1][2]) + costs[i][1];
           dp[i][2] = min(dp[i-1][0],dp[i-1][1]) + costs[i][2];
       }
       int ret = min(dp[n-1][0],min(dp[n-1][1],dp[n-1][2]));
       return ret;
    }
};

以上就是本篇文章的5道動態(tài)規(guī)劃習(xí)題,還是建議大家在做動態(tài)規(guī)劃習(xí)題的時候要多畫圖。文章來源地址http://www.zghlxwxcb.cn/news/detail-480776.html

到了這里,關(guān)于60題學(xué)會動態(tài)規(guī)劃系列:動態(tài)規(guī)劃算法第三講的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【算法學(xué)習(xí)】簡單多狀態(tài)-動態(tài)規(guī)劃

    【算法學(xué)習(xí)】簡單多狀態(tài)-動態(tài)規(guī)劃

    ? ? ? ? 本篇博客記錄動態(tài)規(guī)劃中的簡單多狀態(tài)問題。 ? ? ? ? 在之前的動態(tài)規(guī)劃類型的題中,我們每次分析的都只是一種或者某一類的狀態(tài),定義的dp表也是圍繞著一種狀態(tài)來的。 ? ? ? ? 現(xiàn)在可能對于一種狀態(tài),存在幾種不同的子狀態(tài),在狀態(tài)轉(zhuǎn)移過程中相互影響。此時

    2024年01月18日
    瀏覽(25)
  • 算法沉淀 —— 動態(tài)規(guī)劃篇(簡單多狀態(tài)dp問題上)

    幾乎所有的動態(tài)規(guī)劃問題大致可分為以下5個步驟,后續(xù)所有問題分析都將基于此 1.、狀態(tài)表示:通常狀態(tài)表示分為以下兩種,其中更是第一種為主。 以i為結(jié)尾 ,dp[i] 表示什么,通常為代求問題(具體依題目而定) 以i為開始 ,dp[i]表示什么,通常為代求問題(具體依題目而

    2024年04月11日
    瀏覽(31)
  • 【算法優(yōu)選】 動態(tài)規(guī)劃之簡單多狀態(tài)dp問題——貳

    動態(tài)規(guī)劃相關(guān)題目都可以參考以下五個步驟進行解答: 狀態(tài)表示 狀態(tài)轉(zhuǎn)移?程 初始化 填表順序 返回值 后面題的解答思路也將按照這五個步驟進行講解。 給定一個整數(shù)數(shù)組prices,其中第 prices[i] 表示第 i 天的股票價格 設(shè)計一個算法計算出最大利潤。在滿足以下約束條件下,

    2024年04月12日
    瀏覽(24)
  • 算法沉淀 —— 動態(tài)規(guī)劃篇(簡單多狀態(tài)dp問題下)

    算法沉淀 —— 動態(tài)規(guī)劃篇(簡單多狀態(tài)dp問題下)

    幾乎所有的動態(tài)規(guī)劃問題大致可分為以下5個步驟,后續(xù)所有問題分析都將基于此 1.、狀態(tài)表示:通常狀態(tài)表示分為基本分為以下兩種,其中更是以第一種為甚。 以i為結(jié)尾 ,dp[i] 表示什么,通常為代求問題(具體依題目而定) 以i為開始 ,dp[i]表示什么,通常為代求問題(具

    2024年04月16日
    瀏覽(23)
  • 動態(tài)規(guī)劃之簡單多狀態(tài)

    動態(tài)規(guī)劃之簡單多狀態(tài)

    1.題目鏈接:按摩師 2.題目描述:一個有名的按摩師會收到源源不斷的預(yù)約請求,每個預(yù)約都可以選擇接或不接。在每次預(yù)約服務(wù)之間要有休息時間,因此她不能接受相鄰的預(yù)約。給定一個預(yù)約請求序列,替按摩師找到最優(yōu)的預(yù)約集合(總預(yù)約時間最長),返回總的分鐘數(shù)。

    2024年02月09日
    瀏覽(20)
  • 【動態(tài)規(guī)劃】簡單多狀態(tài)

    【動態(tài)規(guī)劃】簡單多狀態(tài)

    題目鏈接 狀態(tài)表示 dp[i] 表示到i位置的時候預(yù)約的最大時長。但是這個題目我們可以選擇接或不接。因此可以繼續(xù)劃分為兩個子狀態(tài): f[i] 表示:到i位置時接受的最大時長 g[i] 表示:到i位置時不接受的最大時長 狀態(tài)轉(zhuǎn)移方程 初始化 因為這個題目比較簡單,所以不需要使用

    2024年02月15日
    瀏覽(23)
  • c++--簡單多狀態(tài)動態(tài)規(guī)劃問題

    c++--簡單多狀態(tài)動態(tài)規(guī)劃問題

    PS:以下代碼均為C++實現(xiàn) 1.按摩師? 力扣 一個有名的按摩師會收到源源不斷的預(yù)約請求,每個預(yù)約都可以選擇接或不接。在每次預(yù)約服務(wù)之間要有休息時間,因此她不能接受相鄰的預(yù)約。給定一個預(yù)約請求序列,替按摩師找到最優(yōu)的預(yù)約集合(總預(yù)約時間最長),返回總的分鐘

    2024年02月14日
    瀏覽(32)
  • 「動態(tài)規(guī)劃」簡單多狀態(tài)dp問題

    「動態(tài)規(guī)劃」簡單多狀態(tài)dp問題

    以經(jīng)典問題“打家劫舍”來解釋簡單多狀態(tài)dp問題和解決方法 題目鏈接:打家劫舍I 這種問題就是在某一個位置有多個狀態(tài)可以選擇,選擇 不同的狀態(tài) 會影響 最終結(jié)果 在這道題中就是小偷在每一個房屋,可以選擇偷或不偷,每一次選擇都會影響最終偷竊金額 狀態(tài)表示 因為

    2024年03月15日
    瀏覽(29)
  • 【動態(tài)規(guī)劃】簡單多狀態(tài)dp問題(2)買賣股票問題

    【動態(tài)規(guī)劃】簡單多狀態(tài)dp問題(2)買賣股票問題

    買賣股票問題 傳送門:力扣309. 最佳買賣股票時機含冷凍期 題目: 1.1 題目解析 越難的dp問題,看示例只能起到了解題目的效果,一般推不出啥普遍的規(guī)律,所以接下來就是我們的算法原理,通過動歸的思想去理解,才會豁然開朗! 1.2 算法原理 1.2.1 狀態(tài)表示 我們需要通過經(jīng)

    2024年02月12日
    瀏覽(40)
  • 算法提高-動態(tài)規(guī)劃-狀態(tài)機模型

    這題比較簡單,主要是學(xué)習(xí)一下狀態(tài)機的模版(如何定義狀態(tài),dp方程如何推導(dǎo))。 再學(xué)一個知識點:線性dp(i由i-1遞推過來)可以用滾動數(shù)組優(yōu)化空間復(fù)雜度 限制購買天數(shù) 這里也是線性dp,當然可以用滾動數(shù)組優(yōu)化,但是之前大盜阿福寫過了,這里就樸素版本了 限制了賣

    2024年02月15日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包