1. 程式人生 > >石子合併(一)

石子合併(一)

描述    有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;
}