282. Combinación de piedras (intervalo dp)

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 7el 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;
}

Supongo que te gusta

Origin blog.csdn.net/zhi6fui/article/details/128574812
Recomendado
Clasificación