區間DP經典 石子合併

2022-03-11 14:12:14 字數 1156 閱讀 3681

題目鏈結

題意:環形的一群石子,每次可以選擇相鄰的兩堆合併,分數為新得到的一堆石子,求將這片石子合併成一堆的最大和最小分數

輸入:第一行乙個正整數n,其後n個數代表每堆石子的個數

分析:第一次寫的時候我想當然的寫的狀態轉移方程是dpx[l][r]=max(dpx[l+1][r]+a[l][r],dpx[l][r-1]+a[l][r]);(dpx是指這個dp陣列用來求最大分數),想的是左右逼近,但是我這個狀態轉移方程有個非常致命的缺點,那就是合併的兩堆石頭,一定有一堆是沒經過合併的,這很明顯無法代表全部情況,萬一正解就是左邊一半合併成一起,右邊一半合併成一起,然後左右合併,我的演算法就肯定得不到答案。

搜了搜正解,正解狀態轉移方程是dp1[l][r]=max(dp1[l][r],dp1[l][k]+dp1[k+1][r]+d(l,r));通過列舉乙個k來實現將左右兩堆合併在一起的情況

然後再注意題目中的石子是成環的,所以需要用2n的陣列來儲存,最後遍歷也是同樣。

另外dp[i][i]這種單一陣列的分數是0,所以dp2陣列決不能一開始fill成inf,只能在乙個具體的定義下設為inf,具體看**

#includeusing

namespace

std;

typedef

long

long

ll;const

int inf=1

<<30

;const

int maxn=210

;const

double pi=acos(-1

);const

int mod=1e9+7

;int

a[maxn],sum[maxn];

intdp1[maxn][maxn],dp2[maxn][maxn];

int d(int x,int

y)int

main()

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

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

int mx=0,mn=inf;

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

cout

return0;

}

經典 區間dp 合併石子

題目鏈結 這個動態規劃的思是,要得出合併n堆石子的最優答案可以從小到大列舉所有石子合併的最優情況,例如要合併5堆石子就可以從,最優的2 3和1 4中得到最佳的答案。從兩堆最優到三堆最優一直到n堆最優。狀態轉移方程式 dp i j min dp i k dp k 1 j 複雜度為o n 3 inclu...

石子合併 (區間DP

問題描述 在乙個操場上擺放著一行共n堆的石子。現要將石子有序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆石子數記為該次合併的得分。請編輯計算出將n堆石子合併成一堆的最小得分和將n堆石子合併成一堆的最大得分。輸入檔案 輸入第一行為n n 1000 表示有n堆石子,第二行為n個用空...

石子合併 區間dp

有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。假設dp 1 4 表示將區間1 4的石子合併所花費的代價。dp 1 4 可以劃分為dp 1 1 dp 2...