有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 個數,分別表示...