实验目的:
练习动态规划
实验内容:
有n堆石子排成一排,每堆石子有一定的数量,现要将n堆石子合并成为一堆,合并只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和, 经过n-1次合并后成为一堆,求出总代价的最小值。
输入描述:有多组测试数据,输入到文件结束。每组测试数据的第1行有一个整数n, 表示有n堆石子,接下来的一行有n(0<n<200)个数,分别表示这n堆石子的数目,用空格隔开。
输出描述:输出总代价的最小值,占单独的一行。
输入样例:
3
1 2 3
7
13 7 8 16 21 4 18
样例输出:
9
239
思路:
刚开始想用贪心,每次把最小的相邻的两堆合并,但手写连样例都过不去,所以不能用贪心,全局最优要动态规划。
用dp[i][j]表示第i堆到第j堆合并的最优解,
dp[i][j] = min{dp[i][j] , dp[i][k]+dp[k+1][j]+ cost(i,j)}
k在[i,j)之间,
cost是i到j的花费,可以以空间换时间不用每次求,用一维数组存0到i的花费,cost(i,j) = cost(j) - cost(i) + a[i]。
最后dp[0][n-1]即为答案
代码
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#define MAXN 205
#define INF 0x3f3f3f3f
using namespace std;
int main()
{
int n;
int a[MAXN];
int cost[MAXN];
while (cin >>n) {
cin >> a[0];
cost[0] = a[0];
for (int i = 1; i < n; i++) {
cin >> a[i];
cost[i] = cost[i - 1] + a[i];
}
vector<vector<int>> dp(n, vector<int>(n, 0)); //建一个n*n的二维数组,初始化为0
for (int i = 0; i < n; i++) {
dp[i][i] = 0;
}
for (int lens = 1; lens < n; lens++) {
for (int i = 0; i < n - lens; i++) {
int j = i + lens;
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] + cost[j] - cost[i] + a[i]);
}
}
}
cout << dp[0][n - 1];
}
return 0;
}
结果
总结:
要按长度递增来dp,不能按位置dp
标签:求解,int,石子,lens,++,cost,dp 来源: https://blog.csdn.net/lllzzzhhh2589/article/details/121233456
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。