合并石子(直线版)tyvj1055

很菜,很菜,这么一个简单的题写了好几天!

这是网上的版本,好理解,推荐

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=1<<30;
const int maxn=310;
int s[maxn],f[maxn][maxn],n;
int main()
{
	scanf("%d",&n);
	int x;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		s[i]=s[i-1]+x;
		f[i][i]=0;
	 } 
	 for(int l=1;l<=n;l++)
	 	for(int i=1;i<=n;i++)
	 	{
	 		int j=i+l;
	 		f[i][j]=inf;
	 		if(j>n) break;
	 		for(int k=i;k<j;k++)
	 			f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
		 }
	 		
	printf("%d\n",f[1][n]);
}

 一本通的版本,不好写

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100;
int s[maxn],f[maxn][maxn],fm[maxn][maxn],n;
int main()
{
	scanf("%d",&n);
	memset(f,0x3f3f3f3f,sizeof(f));
	//memset(fm,0,sizeof(fm));
	int x;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		s[i]=s[i-1]+x;
		f[i][i]=fm[i][i]=0;
	 } 
	 for(int i=n-1;i>=1;i--)//这里必须是倒着开始的,打表即可 
	 	for(int j=i+1;j<=n;j++)
	 		for(int k=i;k<j;k++)
			 //这里只能从i开始,不能从i+1开始,否则的话k+1就等于i+2了,不能存放在i和j中间 
	 		{	
	 			f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
	 			fm[i][j]=max(fm[i][j],fm[i][k]+fm[k+1][j]+s[j]-s[i-1]);
	 			//cout<<i<<j<<k<<" "<<f[i][j]<<endl;打表的过程 
			 }
	printf("%d\n%d",f[1][n],fm[1][n]);
}

 

posted @ 2017-07-03 11:37  xinyimama  阅读(88)  评论(0编辑  收藏  举报