演算法課8-Dynamic Programming⭐️
動態規劃是常考演算法,將指數級的問題降到多項式級別。
動態規劃和分治法都是將問題劃分成子問題進行求解,它們的區別主要是:
- 分治法的子問題無重疊
- 動態規劃的子問題有重疊,並且重疊的個數是指數級別的
動態規劃和貪心法的相同之處是原問題包含子問題的最優解,而它們的區別在於:
- 貪心法只看區域性最優,最終達到全域性最優
- 對於動態規劃局部最優不一定是全域性最優
1. Weighted interval scheduling
帶權重的最大相容子集,不能用貪心法進行求解,需要考慮動態規劃的解法。首先將活動按照結束時間排序。兩種情況,一種是選當前的j,那麼最優解等於從後往前找第一個與j不衝突的活動(使用二分查詢加快速度)的opt加上j的權重,一種是不選j,那麼最優解等於j的前一個活動的最優解。如下式:
ps.若按照開始時間排序,要反過來找,那麼opt(i)可以定義為,i~n個活動,p(i)是從前往後找第一個不衝突的活動。opt(n+1)=0,return opt(1)。
2. Segmented least squares
線段擬合點集問題,希望線段儘量少,error儘量小。
error定義為E+cL ,E是平方誤差之和,L是線段條數。
opt(j) 是的最小error,e(i,j)是的最小平方誤差
這個演算法的瓶頸在於計算,對j要掃一遍,j固定了,i要掃一遍,i固定了,在i j之間要掃一遍, 使得演算法的效率是.
3. 買賣股票系列
- 只能買賣一次
Best Time to Buy and Sell a Stock
f(j):第j次賣出的最優解, f(1)=0, return ,兩種情況,第一種是當天賣出,第二種是前j-1天買入,第j天賣出,第二種情況和第j-1天賣出的區別就是第j天的價格減去第j-1天的價格。
一個直觀的想法是說維護到目前為止價格的最低點,用上一行減去下一行即可得到最大利潤。
5 | 2 | 7 | 13 | 1 | 9 |
---|---|---|---|---|---|
5 | 2 | 2 | 2 | 1 | 1 |
這道題還可以用分治法做,詳見上一篇博文。
- 買賣兩次
Best Time to Buy and Sell Stock III
設定兩個dp陣列,是第i天第一次賣出最大收益,是第i天第二次賣出最大收益。
思路1:
即為前j天的最大收益
時間 空間
思路2:
return
時間 空間
程式碼:
#include <iostream>
using namespace std;
int sale[100005];
int t;
int dp1[100005];
int dp1_max[100005];
int dp2[100005];
int main(){
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&sale[i]); //這裡使用cin會超時
dp1[i]=0;
dp2[i]=0;
}
int res=0;
for(int i=1;i<n;i++){
dp1[i]=max(dp1[i-1]+sale[i]-sale[i-1],0);
dp1_max[i]=max(dp1_max[i-1],dp1[i]); //最大值儲存別寫錯
dp2[i]=max(dp1_max[i-1],dp2[i-1]+sale[i]-sale[i-1]);
res=max(res,dp2[i]);
}
cout<<res<<endl;
}
return 0;
}
-
- dp[i, j] represents the max profit up until prices[j] using at most i transactions.
- dp[i, j] = max(dp[i, j-1], prices[j] - prices[jj] + dp[i-1, jj]) { jj in range of [0, j-1] }
= max(dp[i, j-1], prices[j] + max(dp[i-1, jj] - prices[jj])) - dp[0, j] = 0; 0 transactions makes 0 profit
- dp[i, 0] = 0; if there is only one price data point you can’t make any transaction.
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (n <= 1)
return 0;
//if k >= n/2, then you can make maximum number of transactions.
if (k >= n/2) {
int maxPro = 0;
for (int i = 1; i < n; i++) {
if (prices[i] > prices[i-1])
maxPro += prices[i] - prices[i-1];
}
return maxPro;
}
int[][] dp = new int[k+1][n];
for (int i = 1; i <= k; i++) {
int localMax = dp[i-1][0] - prices[0];
for (int j = 1; j < n; j++) {
dp[i][j] = Math.max(dp[i][j-1], prices[j] + localMax);
localMax = Math.max(localMax, dp[i-1][j] - prices[j]);
}
}
return dp[k][n-1];
}
public int maxProfit(int[] prices) {
//當前是買入狀態(k<=i天買入,沒賣出)
int[]hold=new int[prices.length+1];
int[]sold=new int[prices.length+1];//賣出狀態
int[]rest=new int[prices.length+1];//冷靜狀態
hold[0]=Integer.MIN_VALUE;
sold[0]=0;
rest[0]=0;
for(int i=1;i<prices.length+1;i++){
//買前需要冷靜
hold[i]=Math.max(hold[i-1],rest[i-1]-prices[i-1]);
//賣前需要買
sold[i]=hold[i-1]+prices[i-1];
//冷靜期之前要麼是休息要麼是賣掉了
rest[i]=Math.max(rest[i-1],sold[i-1]);
}
return Math.max(rest[prices.length],sold[prices.length]);
}
public int maxProfit(int[] prices, int fee) {
if (prices.length <= 1) return 0;
int days = prices.length, buy[] = new int[days];
int sell[] = new int[days];
buy[0]=-prices[0]-fee;
for (int i = 1; i<days; i++) {
// keep the same as day i-1, or buy from sell status at day i-1
buy[i] = Math.max(buy[i - 1], sell[i - 1] - prices[i] - fee);
// keep the same as day i-1, or sell from buy status at day i-1
sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);
}
return sell[days - 1];
}
4. 最長遞增子序列
LeetCode Longest increasing subsequence
一個錯誤的思路
dp[i]=max{dp[p(i)]+1,dp[i-1]} 選i或者不選i,如果選,從後往前找到第一個小於i的值的dp值加1,這個思路不對的原因在於,沒辦法保證第一個小於i的值的狀態是選了這個值的狀態,也就是說,可能沒有選這個p(i),它的當前最大值不能保證合法。
- 思路1
dp[i]是以i結尾的最長遞增子序列,那麼狀態轉移應該是,從i往前找,比i小的位置j的dp值加1中的最大值,注意,後面的數不一定比前面的大。最後返回的是dp值中最大的那一個。
public int lengthOfLIS(int[] nums) {
if(nums.length==0) return 0;
int[]dp=new int[nums.length];
Arrays.fill(dp,1);
int result=1;
for(int i=1;i<nums.length;i++){
for(int j=i-1;j>=0;j--){
if(nums[j]<nums[i]){
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
result
相關推薦
演算法課8-Dynamic Programming⭐️
動態規劃是常考演算法,將指數級的問題降到多項式級別。
動態規劃和分治法都是將問題劃分成子問題進行求解,它們的區別主要是:
分治法的子問題無重疊
動態規劃的子問題有重疊,並且重疊的個數是指數級別的
動
漫談演算法 動態規劃 Dynamic Programming
Dynamic Programming一直以來是自己比較弱的一部分,希望可以在這一塊有所提升。 動態規劃,Dynamic Programming。這裡的programming沒有翻譯成程式設計,是因為,這裡的programming的意思是指一個tabular method。其實這也暗示了DP
轉 演算法-動態規劃 Dynamic Programming--從菜鳥到老鳥
個人分類: 演算法
版權宣告:本文為博主原創文章,轉載請標明出處。 https://blog.csdn.net/u013309870/article/details/75193592
前言
最近在牛客網上做了幾套公司的真題,發現有關動態規劃(Dynamic Programming)演算
演算法-動態規劃 Dynamic Programming--從菜鳥到老鳥
前言
最近在牛客網上做了幾套公司的真題,發現有關動態規劃(Dynamic Programming)演算法的題目很多。相對於我來說,演算法裡面遇到的問題裡面感覺最難的也就是動態規劃(Dynamic Programming)演算法了,於是花了好長時間,查找了相關
Dynamic Programming中的 Bellman-Ford演算法
Shortest Paths with negative weights
Dynamic Programming
Pseudocode
// Shortest paths with negative edges
Shortest-Path(G, t) {
一文弄懂動態規劃(DP Dynamic Programming)下樓梯,國王和金礦,揹包問題,Dijkstra演算法
動態規劃
參考連結
漫畫演算法,什麼是動態規劃?
DP
動態規劃是一種分階段求解決策問題的數學思想
題目一
問:下樓梯問題,有一座高度是10級臺階的樓梯,從下往上走,每跨一步只能向上1級或者2級臺階,請問有多少中走法。
思路
剛才這個題目,你每走一步就有兩
coursera演算法課 Programming Assignment 1:Percolation
這次演算法作業的任務是通過蒙特卡洛模擬來計算 percolation threshold即滲濾閾值。
滲濾:percolation滲濾是一個由絕緣體和金屬隨機分佈的複雜系統。那麼它的金屬分佈在什麼情況下會導致它是一個導體。科學家定義了一個抽象的被稱作perco
演算法初探-動態規劃(Dynamic Programming)
程式設計之中接觸到很多關於演算法的知識,想來整理一番,算是對自己記憶的一個提醒
1.Coin11Problem 問題為:使用最少的三種面值為1,3,5的硬幣組合出11元。
重要的是狀態以及狀態轉移方程 d(i)=min{ d(i-vj)+1 },其中i-vj >
演算法:解碼方法(動態規劃)—— decode-ways(Dynamic programming)
problem:A string “s” is consisted of number characters. If thesubstring value of one or two adjacent characters in “s” is between 1 and 26
公司聚會喜歡程度計算 演算法(動態規劃)Dynamic Programming
問題:
Professor Stewart is consulting for the president of a corporation that is planning a company party. The company has a hierarchi
五大常見演算法策略之——動態規劃策略(Dynamic Programming)
Dynamic Programming
Dynamic Programming是五大常用演算法策略之一,簡稱DP,譯作中文是“動態規劃”,可就是這個聽起來高大上的翻譯坑苦了無數人,因為看完這個演算法你可能會覺得和動態規劃根本沒太大關係,它對“動態”和“規劃”都沒有太深的體現。
舉個最簡單的例子去先淺顯
HDU 4972 A simple dynamic programming problem
als pos trac article 隨機 simple mat abs ble
隨機輸出保平安
#include <cstdio>
#include <cmath>
#include <iostream>
#inc
2017 UESTC Training for Dynamic Programming
輪廓 multi eof complete ons 球隊 tags clu puts 2017 UESTC Training for Dynamic Programming
A 思維, 或 dp, 很有意思
方法1:
構造法:蛇形安排賽程表算法復雜度:O(N
Dynamic Programming
int rom enc sequence expr common condition dep tro First, think of solution as a linear sequence of decisions.
Second, work backward from
以計算斐波那契數列為例說說動態規劃算法(Dynamic Programming Algorithm Overlapping subproblems Optimal substructure Memoization Tabulation)
ash 麻省理工學院 遞歸樹 經典 top 有關 ctu dynamic 代碼 動態規劃(Dynamic Programming)是求解決策過程(decision process)最優化的數學方法。它的名字和動態沒有關系,是Richard Bellman為了唬人而取的。
[leetcode]Dynamic Programming-121. Best Time to Buy and Sell Stock
ram tran input output algorithm ice dynamic c program one Say you have an array for which the ith element is the price of a given stock o
Dynamic programming language
cost system eat could compute imp with ffi behaviors 動態改變運行時結構
Dynamic programming language, in computer science, is a class of high-leve
動態規劃(dynamic programming)
program 選擇 因此 移動 開始 解決 特征 尋找 ima 1、動態規劃是通過組合字問題的解而解決整個問題的。
2、它與分治法的區別:
分治法是將問題分解為一些獨立的子問題,遞歸的求解各個子問題,然後合並子問題的解而得到源問題的解。
而動態規劃適合用於
動態規劃(dynamic programming)(二、最優子問題與重疊子問題,以及與貪心的區別)
貪心策略 找到 算法 找問題 貪心 模式 解決 策略 最優 一、動態規劃基礎
雖然我們在(一)中討論過動態規劃的裝配線問題,但是究竟什麽時候使用動態規劃?那麽我們就要清楚動態規劃方法的最優化問題中的兩個要素:最優子結構和重疊子問題。
1、最優子結構
1)如果
2018.3.1-2 huffman code and dynamic programming
可能 空間 blog 線圖 bottom div 多重 很多 基礎 這周先是huffman code,這東西是一種對數據進行二進制編碼的方式,這樣子編碼可以壓縮空間,算是一種壓縮算法。比如一串數據裏只有a,b,c,d四個字節,一般可能會覺得就00,01,10,11來指代這四