石子合并问题可以在南京邮电大学OJ1225提交验证,我按照自己的思想写了一个贪心算法,结果出错了估计也有人用犯此错误,给出错误案例:
6
3 4 6 5 4 2
\
贪心:
3 4 6 5 4 2
5 4 6 5 4 得分:5
9 6 5 4 得分:9
9 6 9 得分:9
15 9 得分:15
24 得分:24
总得分:62
合理方案
3 4 6 5 4 2
7 6 5 4 2 得分:7
7 6 5 6 得分:6
7 11 6 得分:11
13 11 得分:13
24 得分:24
总得分:61
用贪心的最小花费为62,动态规划DP的61
贴出错误代码\
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e2 + 7;
int getMaxCost(int *p, int n, int *path);
int getMinCost(int *p, int n, int *path);
int main() {
int n;
while (cin >> n) {
int aryNum[maxn], pathMax[maxn], pathMin[maxn];
for (int i = 0; i < n; ++i)
cin >> aryNum[i];
int minCost = getMinCost(aryNum, n, pathMin);
int maxCost = getMaxCost(aryNum, n, pathMax);
cout << minCost << endl;
cout << maxCost << endl;
}
return 0;
}
int getMaxCost(int *p, int n, int *path) {
int cost[maxn];//path[i]表示第i次合并path[i] 和 path[i] + 1
memcpy(cost, p, n * sizeof (int));
int maxValue = 0, maxCost = 0;
for (int i = 1; i < n; ++i) {
int lastCur = n - i;
path[i] = lastCur;
maxValue = cost[0] + cost[lastCur];
for (int j = 0; j < lastCur; ++j)
if (maxValue < cost[j] + cost[j + 1]) {
maxValue = cost[j] + cost[j + 1];
path[i] = j;
}
maxCost += maxValue;
cost[path[i]] = maxValue;
swap(cost[(path[i] + 1) % (lastCur + 1)], cost[lastCur]);
}
return maxCost;
}
int getMinCost(int *p, int n, int *path) {
int cost[maxn];//path[i]表示第i次合并path[i] 和 path[i] + 1
memcpy(cost, p, n * sizeof (int));
int minValue = 0, minCost = 0;
for (int i = 1; i < n; ++i) {
int lastCur = n - i;
path[i] = lastCur;
minValue = cost[0] + cost[lastCur];
for (int j = 0; j < lastCur; ++j)
if (minValue > cost[j] + cost[j + 1]) { // < 换成了 > 就成了求最小值
minValue = cost[j] + cost[j + 1];
path[i] = j;
}
minCost += minValue;
cost[path[i]] = minValue;
swap(cost[(path[i] + 1) % (lastCur + 1)], cost[lastCur]);
}
return minCost;
}
zzuwenjie 2017-3-22 16:25:17
path[]是用来记录合并顺序的
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 520;
int ary[maxn], b[maxn], dp[maxn][maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--) {
memset(ary, 0, maxn * sizeof (int));
memset(b, 0, maxn * sizeof (int));
memset(dp, 0, maxn * sizeof (int));
int n;
scanf("%d", &n);
for (int i= 0;i < n;++i) {
scanf("%d", ary + i);
b[i] = ary[i];
}
sort(b, b + n);
for (int i= 0; i < n; ++i)
for (int j = 0; j < n;++j)
dp[i + 1][j] = *min_element(dp[i], dp[i]+ j + 1)
+ abs(b[j] - ary[i]);
int m1 = *min_element(dp[n], dp[n] + n);
reverse(ary, ary + n);
for (int i = 0; i < n;++i)
for (int j = 0; j < n; ++j)
dp[i + 1][j] = *min_element(dp[i], dp[i] + j + 1)
+ abs(b[j] - ary[i]);
int m2 = *min_element(dp[n], dp[n] + n);
printf("%d\n", min(m1, m2));
}
return 0;
}
\
\