P1880石子合併

2022-04-12 03:20:35 字數 1743 閱讀 9388

傳送

這是乙個年代久遠的區間dp (好像以前培訓的時候講了,但是現在才想起來去a)

區間dp常用狀態:

f[i][j]:以i為左端點,j為右端點的最優解

第一層迴圈列舉區間長度,第二層迴圈列舉起點,第三層列舉中間的斷點

(貌似寫到這裡這個題就寫完了)

特點:問題能轉換為兩兩合併的問題(such as 能量項鍊,石子合併),當然可以再bt一點弄分解問題

步入正題

我們設f[i][j]為合併i到j的最大得分,g[i][j]為最小得分(**裡會出現一些奇怪的東西)。要合併i到j,則對於i,j之間的乙個k來說,肯定是先合併了i到k,再合併k+1到 j。

而且合併完了還要計算合併i到k與合併k+1到j的得分。得分就是s[i](第i堆石子的個數)+s[i+1]+........+s[j],為了節省時間,我們用字首和的形式計算,即sum[i]=s[1]+s[2]+...+s[i],那麼得分也就是sum[j]-sum[i-1].        

綜上,f[i][j]=max(f[i][k],f[k+1][j])+sum[j]-sum[i-1](i<=kg[i][j]=min(g[i][k],g[k+1][j])+sum[j]-sum[i-1](i<=k我們再來考慮邊界狀態

f[i][i]=0,g[i][i]=0,因為合併i到i相當於沒有合併,不得分

g[i][j]=inf,(取min用),f[i][j]=0(取max用)

這個題還牽扯到環,so這時候就該扯扯環變鏈了

因為n與1相鄰,所以我們不妨把s[n+1]設成與s[1]一樣,這樣就可以處理合併n和1了。

但是合併n到2,3,4...n-1呢?(注意不是2,3,4...n-1到n)

思考過後,我們發現可以使s[n+i]=s[i],這樣就可以處理起點是n的情況了

這樣就可以寫**了(迴圈順序在開頭)

(奇怪的變數名警告)

#include#include

#include

#include

#include

using

namespace

std;

int n,s[209],mitsu[209][209],nobu[209][209],sum[209];//

nobu是最大值,mitsu是最小值

int read()//

一堆快讀

while(ch>='

0'&&ch<='9'

)

if(flag)x=-x;

returnx;}

intmain()

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

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

nobu[st][end]+=sum[end]-sum[st-1

]; mitsu[st][end]+=sum[end]-sum[st-1

]; }

}int maxn=-1,minn=214748364

;

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

統計答案

printf(

"%d\n%d

",minn,maxn);}//

i love akchi mitsuhide and oda nobu naga

另一道區間dp典型題:能量項鍊

p1880 石子合併

先從線性的開始吧。有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。樣例 輸入 3 1 2 3 7 13 7 8 16 21 4 18 輸出 9 239 ...

P1880 石子合併

石子歸併最簡單的情況是一排石子,典型的區間dp問題。dp i j 的含義是區間 i,j 合併之後的最大或最小花費 轉移方程 dp i j max min dp i j dp i k dp k 1 j val i,j 對於區間 i,j 它可以由區間 i,k 和區間 k 1,j 合併而來,合併時,要加上...

洛谷P1880 石子合併

描述 在乙個園形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分.輸入格式 資料的第1行試正整數n,1 n 100,表示有n堆石子.第2行有n個數...