石子合并_直线型 动态规划

1、问题描述(问题来源于NWPU noj1148,不过原题是圆形操场上,是一个环形)

一条道路上摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆。规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。编一程序,读入石子堆数n及每堆的石子数(<=20)。选择一种合并石子的方案,使得做n-1次合并,得分的总和最小; 比如有4堆石子:44 5 9 则最佳合并方案如下:
4 4 5 9 score: 0
8 5 9 score: 8
13 9 score: 8 + 13 = 21
22 score: 8 + 13 + 22 = 43

2、输入

可能有多组测试数据。 当输入n=0时结束! 第一行为石子堆数n(1<=n<=100);第二行为n堆的石子每堆的石子数,每两个数之间用一个空格分隔。


3、输出

合并的最小得分,每个结果一行。


4、问题解析

这个问题和矩阵连乘思路一样


5、代码如下

#include
#include

using namespace std;

int main() {

	int n;//n堆石子
	int i, j,k,sum,tmp;//辅助变量
	while (cin >> n) {
		if (0 == n)break;
		sum=0;
		tmp = INT_MAX;
		vector arr(n);
		vector >min(n, vector(n));//min[i][j]代表合并第i堆到第j堆的最小得分
		for (i = 0; i < n; ++i) {
			cin >> arr[i];
		}
		//给min赋值
		for (i = 0; i < n; ++i) {
			min[i][i] = 0;//初始化为0
		}
		for (i = n - 2; i >= 0; --i) {
			for (j = i + 1; j < n; ++j) {
				for (k = i; k <=j; ++k) {
					sum += arr[k];
				//	cout << "sum的值:" << sum << endl;
				}//end for k
				for (k = i; k < j; ++k) {
					if (tmp > min[i][k] + min[k + 1][j]) {
						tmp = min[i][k] + min[k + 1][j];
					}						
				}//end for k
				min[i][j] = sum+tmp;
				sum=0;
				tmp = INT_MAX;
			}// end for j
		}// end for i
		cout << min[0][n - 1] << endl;
	}
}

你可能感兴趣的:(算法与数据结构)