清北学堂模拟赛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; }