动态规划-题-CSDN博客

23 阅读2分钟

石子合并问题可以在南京邮电大学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[]是用来记录合并顺序的

郑大OJ10403山区修路-第七届河南省省赛

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


\

\