码迷,mamicode.com
首页 > 其他好文 > 详细

code[VS] 1048 石子归并

时间:2015-07-26 22:48:29      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:动态规划   记忆化搜索   

题目描述 Description

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

输入描述 Input Description

第一行一个整数n(n<=100)

第二行n个整数w1,w2...wn  (wi <= 100)

输出描述 Output Description

一个整数表示最小合并代价

样例输入 Sample Input

4

4 1 1 4

样例输出 Sample Output

18

以相邻的石头堆来合并,相当于在一个串中割两半,可以用dp[i][j]表示序号从i到j的石头堆合并的最小cost。dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i][j](i<k<=j)。其中sum[i][j]代表序号i到j石头堆的重量和。我觉得理论上搜索和循环都能做,我用的是搜索,写起来简单无脑。 

#include <bits/stdc++.h>
using namespace std;
int vis[102][102];
int n;
int stone[102];
void init(){
	for(int i=1;i<=102;i++)
	for(int j=1;j<=102;j++)
	vis[i][j]=9999999;
}
int dp(int i,int j){
	if(vis[i][j]<9999999)
	return vis[i][j];
	
	if(j-i==1){
		vis[i][j]=stone[i]+stone[j];
		return vis[i][j];
	}
	if(i==j){
		vis[i][i]=0;
		return 0;
	}
	for(int k=i+1;k<=j;k++){
		int sum=0;
		for(int i1=i;i1<=j;i1++)
		sum+=stone[i1];
		vis[i][j]=min(vis[i][j],dp(i,k-1)+dp(k,j)+sum);
	}
	return vis[i][j];
}

int main(){
	init();
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&stone[i]);
	}
	printf("%d\n",dp(1,n));
} 


版权声明:本文为博主原创文章,未经博主允许不得转载。

code[VS] 1048 石子归并

标签:动态规划   记忆化搜索   

原文地址:http://blog.csdn.net/yuhao199555/article/details/47071235

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!