首页 > 代码库 > 清北学堂模拟赛day7 石子合并加强版

清北学堂模拟赛day7 石子合并加强版

技术分享

技术分享

/*
注意到合并三堆需要枚举两个端点,其实可以开一个数组记录合并两堆的结果,标程好像用了一个神奇的优化
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
#define fo(i,l,r) for(int i = l;i <= r;i++)
#define fd(i,l,r) for(int i = r;i >= l;i--)
using namespace std;
const int maxn = 505;
ll read(){
    ll 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*10+(ch-0);ch=getchar();};
    return x*f;
}
int n;
ll dp[maxn][maxn],dp2[maxn][maxn],val[maxn],sum[maxn];
int main(){
    freopen("merge.in","r",stdin);
    freopen("merge.out","w",stdout);
    n = read();
    memset(dp,127/3,sizeof(dp));
    memset(dp2,127/3,sizeof(dp2));
    fo(i,1,n) val[i] = read();
    fo(i,1,n){
        dp[i][i] dp2[i][i] = 0;
        sum[i] = sum[i-1] + val[i];
    }
    for(int l = 4;l <= n;l+=2){
        for(int i = 1;i + l - 1<= n;i++){
            int j = i + l - 1;
            for(int k1 = i;k1 <= j;k1 += 2){
                for(int k2 = k1 + 1;k2 <= j;k2 += 2){
                    dp[i][j] = min(dp[i][j],dp[i][k1] + dp[k1+1][k2] + dp[k2+1][j] + sum[j] - sum[i-1]);
                }
            }
        }
    }
    cout<<dp[1][n];
    return 0;
} 


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-1);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define putk() putchar(‘ ‘)
ld eps=1e-9;
ll pp=1000000007;
ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
ll gcd(ll a,ll b){return (!b)?a:gcd(b,a%b);}
ll read(){
    ll ans=0;
    char last= ,ch=getchar();
    while(ch<0 || ch>9)last=ch,ch=getchar();
    while(ch>=0 && ch<=9)ans=ans*10+ch-0,ch=getchar();
    if(last==-)ans=-ans;
    return ans;
}
void put(ll a){
    if(a<0)putchar(-),a=-a;
    int top=0,q[20];
    while(a)q[++top]=a%10,a/=10;
    top=max(top,1);
    while(top--)putchar(0+q[top+1]);
}
//head
#define INF 1000000000
#define N 410
int n,f1[N][N],f2[N][N],a[N];
int main(){
    freopen("merge.in","r",stdin);
    freopen("merge.out","w",stdout);
    n=read();
    rep(i,1,n)
        rep(j,1,n)f1[i][j]=f2[i][j]=INF;
    rep(i,1,n)a[i]=a[i-1]+read();
    rep(i,1,n)f2[i][i]=0;
    rep(i,1,n-1)f1[i][i+1]=a[i+1]-a[i-1];
    rep(len,3,n)
    rep(i,1,n-len+1){
        int j=i+len-1;
        rep(k,i,j-1)f2[i][j]=min(f2[i][j],f1[i][k]+f2[k+1][j]+a[j]-a[k]);
        rep(k,i,j-1)f1[i][j]=min(f1[i][j],f2[i][k]+f2[k+1][j]+a[j]-a[i-1]);
    }
    cout<<f2[1][n]<<endl;
    return 0;
}

 

清北学堂模拟赛day7 石子合并加强版