區間DP學習

2021-10-05 16:56:57 字數 3121 閱讀 9615

區間dp,主要思想:在小區間進行dp取得最優解,之後利用各個區間的最優解合併求解最大區間的最優解。

模板(自個寫的,當然應用的時候不要生搬硬套):

for

(int len=

0;len)//區間長度

}}

對於dp陣列的初始化,以及「…」的確定就要開動腦筋,因題而異了。

在某個遊戲中,你接受了乙個任務。這個任務要求你消滅n只狼。這些狼排成一排,每只狼都有兩個攻擊力a和b。如果你消滅乙隻狼,需要的代價是這只狼的a攻擊力加上它旁邊的狼的b攻擊力。每消滅一頭狼,它兩邊的狼(如果有)會並在一起,仍然保持一排。

你需要求出:消滅所有狼的最小代價。

輸入輸入第一行為乙個正整數n。

輸入第二行為n個非負整數,按順序表示每只狼的a攻擊力;第三行為n個非負整數,表示每只狼的b攻擊力。

輸出輸出一行乙個整數,為最小的代價。

樣例輸入

33 5 7

8 2 0

樣例輸出

17提示

對於100%的資料,滿足1≤n≤400,每只狼的a攻擊力和b攻擊力均不超過100000。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

//#define local

#define inf 0x3f3f3f3f

using

namespace std;

const

int n =

500;

int a[n]

;int b[n]

;int dp[n]

[n];

int n,m,i,j;

intmain()

for(

int len=

0;len)//區間長度,列舉0到n-1}}

printf

("%d"

,dp[1]

[n])

;return0;

}

說實話,個人覺得動態規劃就是在列舉的基礎上添了些備忘錄、去掉重疊子問題等等。

核心

dp[i]

[j]=

min(dp[i]

[j],dp[i]

[k-1

]+dp[k+1]

[j]+a[k]

+b[i-1]

+b[j+1]

);

取最小值是必然的,k是分割點,把[i,j]區間分割為兩部分,得以構建方程關係,分割之後剩下乙個k未被計算,所以後面加上消滅第k匹狼的代價。

希望有所收穫,以後遇到啥典題繼續更新。

更新了!!!

題目描述

張老師到了乙個王國去旅遊,王國有n個景點,張老師到達這個城市所在的車站恰好位於第x個景點,這個王國非常特別,恰好所有著名的景點都在分布在直線上,每個景點在座標pi上(單位:公里),張老師身體非常好,每走一公里花費一分鐘。每個景點都有乙個打卡點,並且必須在不遲於相應的時間(時間從張老師到達王國開始計算)前到達才能打卡成功並且給以乙個打卡標記,集齊所這些標記就能獲得乙個大禮包。由於張老師非常想要大禮包,並且因為張老師還著急去下乙個王國旅遊,所以張老師希望用的時間盡量少,你能幫幫張老師嗎?

輸入描述:

輸入的第一行,包含乙個整數n(1≤n≤1000)。

第二行包含n個整數pi(1≤pi≤100000),第i個整數pi為第i個景點的座標(座標從小到大排列)。

最後一行包含n個整數ti(0≤ti≤10,000,000),ti表示第i個景點最遲到達的時間,時間為0則表示張老師所在車站的位置且只有乙個為0。

輸出描述:

輸出所需的最少時間,若無解輸出-1。

示例1輸入

41 2 3 4

0 1 2 3輸出3

此題也是區間dp的乙個典題啊,

觀察發現,在最少時間的前提下走過的點必然是連續的區間設為[l,r],那麼唯一的變化就是終點落在l還是人r,這樣我們可以通過dp來解決,我們設狀態f[l][r][0]表示終點落在l的前提下走完區間[l,最小時間,f[l][r][1]同理終點落在r上,狀態轉移為:

f[l-1][r][0]=min(f[l-1][r][0],f[l][r][0]+p[l]-p[l-1]);

f[l][r+1][1]=min(f[l][r+1][1],f[l][r][0]+p[r+1]-p[l]);

f[l-1][r][0]=min(f[l-1][r][0],f[l][r][1]+p[r]-p[l-1]);

f[l][r+1][1]=min(f[l][r+1][1],f[l][r][1]+p[r+1]-p[r]);

那麼答案就是min(f[1][n][0],f[1][n][1])。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

//#define local

#define inf 0x3f3f3f3f

using

namespace std;

const

int n =

1005

;const

int mod =

998244353

;int n;

int p[n]

,t[n]

;int dp[n]

[n][2]

;int

main()

for(

int k=

1; kint ans=

min(dp[1]

[n][0]

,dp[1]

[n][1]

);printf

("%d"

,ans==inf?-1

:ans)

;return0;

}

區間dp學習筆記

定義 區間動態規劃問題一般都是考慮,對於每段區間,他們的最優值都是由幾段更小區間的最優值得到,是分治思想的一種應用,將乙個區間問題不斷劃分為更小的區間直至乙個元素組成的區間,列舉他們的組合 求合併後的最優值。設f i,j 1 i j n 表示區間 i,j 內的數字相加的最小代價最小區間f i,i 0...

區間dp學習筆記

怎麼辦,膜你賽要掛慘了,下午我還在學區間 dp 不管怎麼樣,計畫不能打亂 4 不 4 為啥我一開始就先弄模板呢?因為這東西看模板就能看懂。for int i 2 i len i 列舉區間長度 for int l 1,r l len 1 r n l r 列舉左端點和右端點 以下你可以搞一下事情 for...

區間DP學習總結

這段時間學習了區間dp,所以試著把學到的東西稍作總結,以備不時之需。學習區間dp首先要弄清區間dp是為了解決什麼問題 一般的dp主要是特徵是一次往往只操作乙個數值或者儲存可以不連續的物品的狀態 比如揹包問題中,每乙個點儲存的狀態中,拿到的物品的編號並不要求一定連續 而區間dp,則是要求dp陣列中每個...