NC50493 石子合并
石子合并
https://ac.nowcoder.com/acm/problem/50493
分析
由于石子摆在圆形操场的四周,因此 堆石子会摆放成一个环,于是不妨将
堆石子复制一份,使得
。
定义 为合并区间
内石子获得的最小得分,有状态转移方程
。同理,定义
为合并区间
内石子获得的最大得分,有状态转移方程
。所求即为
和
。
代码
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
#define N 302
using namespace std;
int dp_min[N][N];
int dp_max[N][N];
int n;
int sum[N];
int a[N];
int main()
{
//初始化
memset(dp_min,0x3f,sizeof(dp_min));
memset(dp_max,0,sizeof(dp_max));
int i,j,k;
cin>>n;
for(i=1;i<=n;i++) scanf("%d",a+i);
for(i=n+1;i<=2*n;i++) a[i]=a[i-n];
//O(1)获得count(i,j)
for(i=1;i<=2*n;i++) sum[i]=sum[i-1]+a[i];
for(j=1;j<=2*n;j++)//右边界
{
for(i=j;i>=1;i--)//左边界
{
if(i==j) dp_min[i][j]=dp_max[i][j]=0;
for(k=i;k<j;k++)//分界点
{
dp_min[i][j]=min(dp_min[i][k]+dp_min[k+1][j]+sum[j]-sum[i-1],dp_min[i][j]);
dp_max[i][j]=max(dp_max[i][k]+dp_max[k+1][j]+sum[j]-sum[i-1],dp_max[i][j]);
}
}
}
int ans_min=0x3f3f3f3f,ans_max=-1;
for(i=1;i<=n-1;i++)
{
ans_min=min(ans_min,dp_min[i][i+n-1]);
ans_max=max(ans_max,dp_max[i][i+n-1]);
}
cout<<ans_min<<endl<<ans_max<<endl;
return 0;
}
查看10道真题和解析

