使用动态规划解决石子合并问题:
动态规划通常用来求解最优化问题,即一个问题有多个解,每个解都有一个目标值,我们希望寻找具有最优值(最小或最大)的解
动态规划算法寻求石子合并时的最大,最小得分,选择相邻的两堆石子堆进行合并,其最终花费的代价与石子堆的排列顺序有关。根据其重叠子问题建立状态转移方程,利用程序进行求解。此问题具有重叠子结构
因此从已有的 i 到 j 的最小得分,与从 i 到 k 的最小得分、从 k+1 到 j 的最小得分、当前步骤从 i 到 j 的合并得分的和的最小值,最大也同此想法。
代码附上:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int M = 220;
int MAX[M][M];
int MIN[M][M];
int num[M];
int sum[M];
int n;
int main() {
printf("请输入石子堆数:\n");
cin >> n;
for (int i = 1;i <= n - 1;i++){
num[n+i]=num[i];
}
sum[0] = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", num + i);
sum[i] = sum[i - 1] + num[i];
}
memset(MIN , -1 ,sizeof(MIN));
for (int l = 1; l <= n; l ++) {
for (int i = 1; i + l - 1 <= n; i++) {
int j = i + l - 1;
if (l == 1) {
MAX[i][j] = 0;
MIN[i][j] = 0;
}
else {
for (int k = i; k < j; k++) {
int maxnum = MAX[i][k] + MAX[k + 1][j] + sum[j] - sum[i - 1];
int minnum = MIN[i][k] + MIN[k + 1][j] + sum[j] - sum[i - 1];
if (MAX[i][j] < maxnum) {
MAX[i][j] = maxnum;
}
if (MIN[i][j] == -1 ||MIN[i][j] > minnum) {
MIN[i][j] = minnum;
}
}
}
}
}
printf("最大得分为:%d\n", MAX[1][n]);
printf("最小得分为:%d\n", MIN[1][n]);
return 0;
}