社区讨论

玄关

P1880[NOI1995] 石子合并参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@m2c13u1y
此快照首次捕获于
2024/10/16 23:30
去年
此快照最后确认于
2025/11/04 17:02
4 个月前
查看原帖
虽然过了但是有疑惑 这串代码求得最小值都没问题,为什么求最大值的时候都多加了个总和sum[N]??? 最后一行都减掉sum[N]就莫名过了
CPP
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;
int N;
int a[250];
int sum[300];
int dp1[250][250],dp2[250][250];
int dfs1(int l,int r)
{
    if(dp1[l][r]) return dp1[l][r];
    if(l==r || l>r) return dp1[l][r]=0;  //加上l>r只是为了少讨论
    int ans=INT_MAX;
    for(int i=l;i<r;i++)
        ans=min(ans,dfs1(l,i)+dfs1(i+1,r)+sum[r]-sum[l-1]);   //合并两个区间所需+合并最终的石头所需,即l~r内所有石头之和
    return dp1[l][r]=ans;
}
int dfs2(int l,int r)
{
    if(dp2[l][r]) return dp2[l][r];
    if(l==r || l>r) return dp2[l][r]=0;  //加上l>r只是为了少讨论
    int ans=-1;
    for(int i=l;i<r;i++)
        ans=max(ans,dfs2(l,i)+dfs2(i+1,r)+sum[r]-sum[l-1]);   //合并两个区间所需+合并最终的石头所需,即l~r内所有石头之和
    return dp2[l][r]=ans;
}
int main()
{
    cin>>N;
    for(int i=1;i<=N;i++) cin>>a[i];
    sum[1]=a[1];
    for(int i=1,j=1;i<=2*N;i++,j++)
    {
        if(i>N) j%=N;
        sum[i]=a[j]+sum[i-1];   //区间扩大两倍
    }
    int minans=INT_MAX,maxans=-1;
    for(int i=1;i<=N;i++)
    {
        for(int j=i+1;j<=N+i;j++)   //分成i~j-1,j~i+N-1两个线性区间(i'==j,即j=N+i时包含(i~~j-1)整个区间)
        {
            minans=min(minans,dfs1(i,j-1)+dfs1(j,i+N-1)+sum[N]);  //别忘加上总和
            maxans=max(maxans,dfs2(i,j-1)+dfs2(j,i+N-1)+sum[N]);
        }
    }
    cout<<minans<<endl<<maxans-sum[N];
}

回复

1 条回复,欢迎继续交流。

正在加载回复...