P1880 [NOI1995] 石子合并

P1880 [NOI1995] 石子合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

本题重要的是是个圆。

圆的通常思维,是把圆拆成两条链

 

这样子 n 变成 2*n(区间dp模板题)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back   //vector函数
#define popb pop_back  //vector函数
#define fi first
#define se second
const int N=210;
//const int M=;
const int inf=0x3f3f3f3f;     //一般为int赋最大值,不用于memset中
//const ll INF=0x3ffffffffffff; //一般为ll赋最大值,不用于memset中
int T,n,a[N],sum[N];
int dp[2][N][N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
    n=read();
    for(int i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
    for(int i=n+1;i<=2*n;i++) a[i]=a[i-n],sum[i]=sum[i-1]+a[i];
    for(int i=1;i<=2*n;i++)
        for(int j=1;j<=2*n;j++) dp[0][i][j]=inf;
    for(int i=1;i<=2*n;i++) dp[0][i][1]=0;
    for(int len=2;len<=n;len++)
        for(int i=1;i+len-1<=2*n;i++)
            for(int j=i;j<=i+len-2;j++)
            {
                dp[0][i][len]=min(dp[0][i][len],dp[0][i][j-i+1]+dp[0][j+1][i+len-j-1]+sum[i+len-1]-sum[i-1]);
                dp[1][i][len]=max(dp[1][i][len],dp[1][i][j-i+1]+dp[1][j+1][i+len-j-1]+sum[i+len-1]-sum[i-1]);
            }
    int ans1=inf,ans2=0;
    for(int i=1;i<=n;i++) ans1=min(ans1,dp[0][i][n]),ans2=max(ans2,dp[1][i][n]);
    printf("%d\n%d",ans1,ans2);
    return 0;
}

 

posted @ 2023-03-01 22:03  QAQ啥也不会  阅读(32)  评论(0编辑  收藏  举报