区间DP
一条直线上的石子合并
题目:石子合并1
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N],f[N][N],g[N][N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1];
}
for(int l=2;l<=n;l++)
{
for(int i=1;i+l-1<=n;i++)
{
int r=i+l-1;
f[i][r]=1e8;
g[i][r]=0;
for(int k=i;k<r;k++)
{
f[i][r]=min(f[i][r],f[i][k]+f[k+1][r]+a[r]-a[i-1]);
}
}
}
cout<<f[1][n]<<endl;
return 0;
}
成环的石子合并
题目:石子合并2
成环则存2倍长度进行处理,注意边界
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int a[N],sum[N],f[N][N],g[N][N];
int main()
{
int n;
cin>>n;
memset(g,0,sizeof(g));
memset(f,0x3f,sizeof(f));
sum[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i+n]=a[i];
}
for(int i=2;i<n*2;i++)
{
sum[i]=sum[i-1]+a[i];
f[i][i]=g[i][i]=0;
}
for(int l=2;l<=n;l++)
{
for(int i=1;i+l-1<n*2;i++)
{
int r=i+l-1;
for(int k=i;k<r;k++)
{
f[i][r]=min(f[i][r],f[i][k]+f[k+1][r]+sum[r]-sum[i-1]);
g[i][r]=max(g[i][r],g[i][k]+g[k+1][r]+sum[r]-sum[i-1]);
}
}
}
int in=1e8,ax=-1;
for(int i=1;i<=n;i++)
{
//cout<<f[i][i+n-1]<<" "<<g[i][i+n-1]<<endl;
in=min(in,f[i][i+n-1]);
ax=max(ax,g[i][i+n-1]);
}
cout<<in<<endl<<ax;
return 0;
}