![P1880 [NOI1995]石子合并(区间DP) P1880 [NOI1995]石子合并(区间DP)](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
题目链接:https://www.luogu.org/problemnew/show/P1880
题目大意:中文题目
具体思路:和上一篇的思路是差不多的,也是对于每一个小的区间进行处理,然后再归并到大区间上。
这里的递推式:dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
AC代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 4e2+;
const int mod =1e6;
# define LL_inf 0x3f3f3f3f3f3f3f
int dp1[maxn][maxn];
int dp2[maxn][maxn];
int sum[maxn],a[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i];
a[i+n]=a[i];
}
for(int i=n+;i<=*n;i++){
sum[i]=sum[i-]+a[i];
}
for(int i=;i<=n;i++){
for(int j=,pos=j+i;j<*n&&pos<*n;j++,pos=j+i){
dp1[j][pos]=inf;
for(int k=j;k<pos;k++){//注意这里不能等于,因为一个数的时候应该是按照0来算的
dp1[j][pos]=min(dp1[j][pos],dp1[j][k]+dp1[k+][pos]+sum[pos]-sum[j-]);
dp2[j][pos]=max(dp2[j][pos],dp2[j][k]+dp2[k+][pos]+sum[pos]-sum[j-]);
}
}
}
int minn=inf,maxx=;
for(int i=;i<=n;i++){
minn=min(minn,dp1[i][i+n-]);
maxx=max(maxx,dp2[i][i+n-]);
}
printf("%d\n%d\n",minn,maxx);
return ;
}