模板 動態規劃 區間dp

2022-05-07 23:00:26 字數 2883 閱讀 5532

因為昨天在codeforces上設計的區間dp錯了(錯過了上紫的機會),覺得很難受。看看學長好像也有學,就不用看別的神犇的了。

區間dp處理環的時候可以把序列延長一倍。

for(int len = 1; len<=n; len++) }}

首先,使用四邊形優化要滿足下面的性質:

當小區間包含在大區間中,則小區間的成本不高於大區間的成本

對於 $a定理:若能證明 $cost$ 滿足1和2,則 $dp$ 也滿足2。

定理:記 $s[i][j]$ 為 $dp[i][j]$ 取得最值時的分割點的下標 $k$ ,若 $dp$ 滿足2,則 $s[i][j]$ 單調,也就是 $s[i][j]≤s[i][j+1]≤s[i+1][j+1]$ 。

$dp[i][j]=min\+cost[i][j],s[i][j-1]≤k≤s[i+1][j]$

我們減少了k的列舉量,而k的列舉量為 $o(n^2)$。

而上述定理的證明……先省略吧……那我們只需要證明cost滿足1和2,就可以使用四邊形優化了。

另外要注意

s[i][i]=i;

for(int len = 2; len<=n; len++) 

}dp[i][j]+=cost[i][j];}}

事先計算出 $cost[i][j]$ 就可以了。

來,開始看看學長搞了什麼。

看了學長說的,設 $dp[i][j]$ 為把 $[i,j]$ 塗成指定顏色需要的最少cost,那麼轉移的時候怎麼搞呢?

#includeusing

namespace

std;

#define ll long long

intn;

int a[205

];int prefix[205

];int dp[205][205

];inline

int sum(int l,int

r) int

main()

for(int i=n+1; i<=2*n; i++)

for(int len = 1; len<=n; len++)

//printf("sum(i,j)=%d dp[%d][%d]=%d\n",sum(i,j),i,j,dp[i][j]);

} }

int ans=0x3f3f3f3f

;

for(int i=1;i<=n;i++)

printf(

"%d\n

",ans);

memset(dp,

0,sizeof

(dp));

for(int len = 1; len<=n; len++) }}

ans=0

;

for(int i=1;i<=n;i++)

printf(

"%d\n

",ans);}}

view code

水題,記得要擴大一倍。

使用四邊形不等式時,運算必須是最小值,最大值不滿足單調性,如下。

#includeusing

namespace

std;

#define ll long long

intn;

int a[205

];int prefix[205

];int dp[205][205

];int dp2[205][205

];int s[205][205

];inline

int sum(int l,int

r) int

main()

for(int i=n+1; i<=2*n; i++)

for(int len = 2; len<=n; len++)

//printf("k=%d\n",k);

} dp[i][j]+=sum(i,j);

//printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);

} }

for(int len = 1; len<=n; len++)

if(dp[i][j]!=dp2[i][j])

printf(

"sum(i,j)=%d dp[%d][%d]=%d dp2[%d][%d]=%d\n

",sum(i,j),i,j,dp[i][j],i,j,dp2[i][j]);}}

int ans=0x3f3f3f3f

;

for(int i=1;i<=n;i++)

printf(

"%d\n

",ans);

for(int i=1; i<=2*n; i++)

memset(dp,

0,sizeof

(dp));

memset(dp2,

0,sizeof

(dp2));

for(int len = 2; len<=n; len++)

}dp[i][j]+=sum(i,j);}}

for(int len = 1; len<=n; len++)

if(i<10&&j<10&&dp[i][j]!=dp2[i][j])

printf(

"sum(i,j)=%d dp[%d][%d]=%d dp2[%d][%d]=%d\n

",sum(i,j),i,j,dp[i][j],i,j,dp2[i][j]);}}

ans=0

;

for(int i=1;i<=n;i++)

printf(

"%d\n

",ans);}}

view code

動態規劃 區間DP 計數類DP

acwing 282.石子合併 區間dp的特點是狀態表示的時候表示的是某乙個區間的情況 動態規劃模型分析 即 不管石子如何合併,最後一步的操作一定是將兩堆石子合併 把步驟回到倒數第一步。當在做最後一次操作時遍歷所有區間,將最後一步最小的情況記錄進f陣列裡 部分如下 全域性變數 const int n...

動態規劃 區間

真是乙個思維巧妙的毒瘤題。因此我們直接利用上面的性質來dp.設f i j f i j f i j 表示線段按右端點排序後第i ii條,j,rj j,r j j,rj 只被覆蓋了一次的最小代價,1,rj 1,r j 1,rj 全部被覆蓋的方案數。那麼,我們需要根據上乙個線段j jj和i ii的位置關係...

Vijos p1150 動態規劃 區間dp

某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節省電...