區間dp 石子合併 矩陣鏈乘法

2021-10-10 10:20:25 字數 1593 閱讀 1412

有n堆石子圍成乙個圈,每一堆石子可以和相鄰的一堆合併得到新的一堆,所得的分數是新的一堆的數量。

所有的石子合併成一堆後,最大的分數,最小的分數是多少。

這是乙個環,需要拆分成鏈,把這n堆,複製一遍,變成2n堆。

dp的時候還是得保證長度為n。dp_min[i][j]表示合併i~j這個區間所得到的最小的分數。

狀態轉移:dp_min[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + a[j] - a[i-1])

a陣列是字首和

#pragma warning(disable:4996)

#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 505;

const ll mod = 10000;

int a[205], dp_min[205][205], dp_max[205][205];

int main()

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

for (int l = 2; l <= n; l++)//長度的取值最多為n

}} max = -0x3f3f3f;

min = 0x3f3f3f;

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

printf("%d\n%d\n", min, max);

return 0;

}

計算n個矩陣相乘變成1個矩陣,最少的運算次數。

比如乙個n1 x m和乙個 m x n2 的矩陣相乘,計算的次數就是n1 * m * n2

輸入是n+1個數,第i個矩陣用第i個數和第i+1個數來表示維度,

區間dp,區間長度最小為2,最大為n。

dp[i][j]表示i~j這個區間內,全部乘起來,需要的最少的乘法運算次數。

狀態轉移:

dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + a[i-1]*a[k] * a[j])

#pragma warning(disable:4996)

#include#include#include#include#include//沒用的標頭檔案太多,刪去了一些,不然顯得太長,

//無法編譯的話,就再加上標頭檔案吧

#define site set::iterator

using namespace std;

typedef long long ll;

const int inf = 1e9 + 10;

const int mod = 1000007;

const int maxn = 1e7;

ll n;

ll p[1005], m[1005][1005], s[1005][1005];

int main()

for (ll l = 2; l <= n; l++)

}} }

cout << m[1][n] << endl;

return 0;

}

石子合併 (區間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...

石子合併 (區間DP)

題目鏈結 描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入第一行有乙個整數n,表示有n堆石子。接下來的一行有n 0 n 200 個數,分別表示...