Hay N montones de piedras dispuestas en fila, y sus números son 1, 2, 3,..., N.
Cada montón de piedras tiene una determinada cualidad, que puede describirse mediante un número entero. Ahora estos NN montones de piedras deben fusionarse en un solo montón.
Sólo se pueden fusionar dos pilas adyacentes cada vez. El costo de la fusión es la suma de las masas de las dos pilas de piedras. Después de fusionar, las piedras adyacentes a las dos pilas de piedras serán adyacentes a la nueva pila. Debido a la orden de selección diferente al fusionarse, el costo total de la fusión también es diferente.
Por ejemplo, si hay 44 montones de piedras 1 3 5 2
, primero podemos fusionar 1 y 2 montones a un costo de 4 para obtener 4 5 2
, y luego fusionar 1 y 2 montones a un costo de 9 para obtener 9 2
, y luego combinar para obtener 11, con un coste total de 4+9+11= veinticuatro;
Si el segundo paso es fusionar 2 y 3 pilas primero, el costo es 7, 4 7
el costo de la última fusión es 11 y el costo total es 4+7+11=22.
El problema es: encontrar un método razonable para minimizar el costo total y generar el costo mínimo.
formato de entrada
Un número NN en la primera línea representa el número de pila NN de piedras.
La segunda línea contiene números NN, que representan la calidad de cada montón de piedras (no más de 1000).
formato de salida
Genere un número entero que represente el costo mínimo.
rango de datos
1≤N≤300
Muestra de entrada:
4
1 3 5 2
Salida de muestra:
22
#include<bits/stdc++.h>
using namespace std;
const int N = 310;
int a[N];
const int INF = 0x3f3f3f;
int main() {
int n;
cin >> n;
int dp[N][N];
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int s[N];
for (int i = 1; i <= n; i++) {
s[i] = s[i - 1] + a[i];
}
int w[N][N];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
w[i][j] = s[j] - s[i - 1];
}
}
//有两种方法:
for (int i = 1; i <= n; i++) {
dp[i][i] = 0;//石子自己本身
}
for (int j = 2; j <= n; j++) { // 按区间进行划分
for (int i = j - 1; i >= 1; i--) {
//从 [i,j]
dp[i][j] = INF;
for (int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + w[i][j]);
}
}
}
/*
*按区间的大小进行划分
* for(int len = 2;len <= n;len++){ //区间的长度[i,j],从小区间到大区间
for(int i = 1; i <= n-len+1;i++){ // 区间的起点
int j = i + len -1;
dp[i][j]=INF;
for(int k = i;k < j;k++){
d[i][j] = min(dp[i][j],dp[i][j] + w[i][j]);
}
}
}
*/
cout << dp[1][n];
return 0;
}