一、心得
二、題目
時間限制:
1000 ms | 記憶體限制:65535 kb
難度:3
描述
有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n-1次合併後成為一堆。求出總的代價最小值。
輸入
有多組測試資料,輸入到檔案結束。
每組測試資料第一行有乙個整數n,表示有n堆石子。
接下來的一行有n(0< n <200)個數,分別表示這n堆石子的數目,用空格隔開
輸出輸出總代價的最小值,佔單獨的一行
樣例輸入
3樣例輸出1 2 3
713 7 8 16 21 4 18
9**239
經典問題
三、分析
* 合併石子.cpp
* 分析:
* 狀態:
* f[i][j]表示把第i堆石子到第j堆石子合併成一堆的最小代價
* sum[j]表示第1堆石子到第j堆石子的和
* 最終狀態:
* f[1][n]
* 初始狀態:
* f[i][i]=0;
* 狀態轉移方程:
* 假設最後一次合併是將(i,k)和(k+1,j)合併
dp過程圖
四、ac**
242ms
1/*2五、注意點* 合併石子.cpp
3* 分析:
4* 狀態:
5* f[i][j]表示把第i堆石子到第j堆石子合併成一堆的最小代價
6* sum[j]表示第1堆石子到第j堆石子的和
7* 最終狀態:
8* f[1][n]
9* 初始狀態:
10* f[i][i]=0;
11* 狀態轉移方程:
12* 假設最後一次合併是將(i,k)和(k+1,j)合併
13* f[i][j]=min(f[i][k]+f[k+1][j]+sum[j]-sum[i-1]) (k>=i&&k<=j)14*
15*16*/
1718 #include 19 #include 20
using
namespace
std;
21int f[205][205
];22
int sum[205
];23
int a[205]; //
用來存這n堆石子
24int
n;25
26void
readdata() 30}
3132
void
printread()
37 cout <
3940
void
initarr_sum() 45}
4647
void
printarr_sum()
51 cout <
5354
void
initarr_f() 60}
61//
初始化62
for (int i = 1; i <= n; i++) 65}
6667
void
printarr_f()
72 cout <
74}7576
void
init()
8485
void
dp() 92}
93}94}
9596
void
printans()
99100
intmain()
108109
return0;
110}
111112
/*113
* 注意點:
114* 1、因為求最小值,所以f要初始化為較大值
115* f[i][j] = 0xfffffff;
116*/
1、因為求最小值,所以f要初始化為較大值f[i][j] = 0xfffffff;
DP 合併石子
矩陣連乘求最小相乘次數的問題和石子合併的問題思路是一樣的,而二者都是典型的dp 石子合併的問題 問題描述 在一條直線上有n堆石子,每堆有一定的數量,每次可以將兩堆相鄰的石子合併,合併後放在兩堆的中間位置,合併的費用為兩堆石子的總數。求把所有石子合併成一堆的最小花費。輸入格式 輸入第一行包含乙個整數n...
dp 合併石子
靈活的dp啊。靈活的思路啊。怎樣去分析乙個你認為是用簡單dp解決的問題呢。就是把問題盡量想得簡單一點。舉個例子,把大象放進冰箱分為幾步 把大象的頭放進冰箱,把大象的尾巴放進冰箱。都是同樣的 放進冰箱 的操作,涉及的資料的規模變小了,這樣 步驟簡化 就可以有點思路。回到說這道題 你合併這11堆石子,你...
合併石子 dp
時間限制 1 sec 記憶體限制 128 mb 提交 7 解決 7 提交 狀態 討論版 命題人 quanxing 在乙個操場上一排地擺放著 堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的 堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。計算出將 堆石子合併成一堆的最小得分。第...