石子合并(一)

描述     有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
7
13 7 8 16 21 4 18
样例输出
9

239


这是一道典型的动态规划问题 类型和基础模型 矩阵连乘一样

求解找到动规方程即可

动规方程   min_cost[i][j]=min(min_cost[i][j],min_cost[i][k]+min_cost[k+1][j]+cun[i][k]+cun[k+1][j]) 


                min_cost代表从 i 到 j 的最少花费 中间进行分堆 递归查找最小花费

                cun代表从 i 到 j 合并需要花费的代价

#include<iostream>
#include<cstring>
using namespace std;
int min_cost[230][230];//存储从 i 到 j 花费的最小代价 
int cun[230][230];//存储从 i 到 j 的总代价
int n;
int array[230];
void search(int a,int b)
{
	if(min_cost[a][b]<10000000)
		return;
	else
	{
		int i;
		for(i=a;i<b;i++)
		{
			search(a,i);
			search(i+1,b);
			min_cost[a][b]=min(min_cost[a][b],min_cost[a][i]+min_cost[i+1][b]+cun[a][i]+cun[i+1][b]);
		}
	}
}
int main()
{
	while(cin>>n)
	{
		int i,j;
		for(i=0;i<n;i++)
			cin>>array[i];
		for(i=0;i<n;i++)
			cun[i][i]=array[i];
		for(i=0;i<n-1;i++)
			for(j=i+1;j<n;j++)
				cun[i][j]=cun[i][j-1]+array[j];
		memset(min_cost,127,sizeof(min_cost));//初始化为最大值 
		for(i=0;i<n;i++)
			min_cost[i][i]=0;
		for(i=1;i<n;i++)
		{
			for(j=0;j<i;j++)
			{
				search(0,j);
				search(j+1,i);
				min_cost[0][i]=min(min_cost[0][i],min_cost[0][j]+min_cost[j+1][i]+cun[0][j]+cun[j+1][i]);
			}		
		}
		cout<<min_cost[0][n-1]<<endl;
	}
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/lb_78596935/article/details/80082813
今日推荐