P1880 [NOI1995]石子合并
题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分。
输入格式
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数。
输出格式
输出共2行,第1行为最小得分,第2行为最大得分。
输入输出样例
输入 #1
4
4 5 9 4
输出 #1
43
54
这道题主要用的是转移方程来求取最大值和最小值,唯一的坑点就是它是一个环!!!坑啊!!!;
#include<bits/stdc++.h> //可爱的万能头
using namespace std;
int n,minl,maxl;
int f1[300][300],f2[300][300];//一个负责max,一个负责min
int num[300],sum[300];
inline int d(int i,int j)//转移方程
{
return sum[j]-sum[i-1];
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>num[i]; //单独输入
for(int i=1;i<=n+n;i++) //因为是一个环,所以需要开到两倍再枚举分界线,最后肯定是最大的
{
num[i+n]=num[i];
sum[i]=sum[i-1]+num[i];
}
for(int p=1;p<n;p++)
{
for(int i=1,j=i+p;(j<n+n)&&(i<n+n);i++,j=i+p)
{
f2[i][j]=0x7f7f7f; //取最大值
for(int k=i;k<j;k++)
{
f1[i][j] = max(f1[i][j],f1[i][k]+f1[k+1][j]+d(i,j)); //进行推
f2[i][j] = min(f2[i][j],f2[i][k]+f2[k+1][j]+d(i,j));
}
}
}
minl=0x7f7f7f;
for(int i=1;i<=n;i++)
{
maxl=max(maxl,f1[i][i+n-1]);
minl=min(minl,f2[i][i+n-1]);
}
cout<<minl<<endl<<maxl; //完美的输出
return 0;
}
大家都懂
#include<bits/stdc++.h>
using namespace std;
int n,minl,maxl;
int f1[300][300],f2[300][300];
int num[300],sum[300];
inline int d(int i,int j)
{
return sum[j]-sum[i-1];
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>num[i];
for(int i=1;i<=n+n;i++)
{
num[i+n]=num[i];
sum[i]=sum[i-1]+num[i];
}
for(int p=1;p<n;p++)
{
for(int i=1,j=i+p;(j<n+n)&&(i<n+n);i++,j=i+p)
{
f2[i][j]=0x7f7f7f;
for(int k=i;k<j;k++)
{
f1[i][j] = max(f1[i][j],f1[i][k]+f1[k+1][j]+d(i,j));
f2[i][j] = min(f2[i][j],f2[i][k]+f2[k+1][j]+d(i,j));
}
}
}
minl=0x7f7f7f;
for(int i=1;i<=n;i++)
{
maxl=max(maxl,f1[i][i+n-1]);
minl=min(minl,f2[i][i+n-1]);
}
cout<<minl<<endl<<maxl;
return 0;
}
求点赞!!!