P1880 [NOI1995]石子合并(区间DP)
题目链接:https://www.luogu.org/problemnew/show/P1880
题目大意:中文题目
具体思路:和上一篇的思路是差不多的,也是对于每一个小的区间进行处理,然后再归并到大区间上。
这里的递推式:dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
AC代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstring> 4 using namespace std; 5 # define ll long long 6 # define inf 0x3f3f3f3f 7 const int maxn = 4e2+100; 8 const int mod =1e6; 9 # define LL_inf 0x3f3f3f3f3f3f3f 10 int dp1[maxn][maxn]; 11 int dp2[maxn][maxn]; 12 int sum[maxn],a[maxn]; 13 int main(){ 14 int n; 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++){ 17 scanf("%d",&a[i]); 18 sum[i]=sum[i-1]+a[i]; 19 a[i+n]=a[i]; 20 } 21 for(int i=n+1;i<=2*n;i++){ 22 sum[i]=sum[i-1]+a[i]; 23 } 24 for(int i=1;i<=n;i++){ 25 for(int j=1,pos=j+i;j<2*n&&pos<2*n;j++,pos=j+i){ 26 dp1[j][pos]=inf; 27 for(int k=j;k<pos;k++){//注意这里不能等于,因为一个数的时候应该是按照0来算的 28 dp1[j][pos]=min(dp1[j][pos],dp1[j][k]+dp1[k+1][pos]+sum[pos]-sum[j-1]); 29 dp2[j][pos]=max(dp2[j][pos],dp2[j][k]+dp2[k+1][pos]+sum[pos]-sum[j-1]); 30 } 31 } 32 } 33 int minn=inf,maxx=0; 34 for(int i=1;i<=n;i++){ 35 minn=min(minn,dp1[i][i+n-1]); 36 maxx=max(maxx,dp2[i][i+n-1]); 37 } 38 printf("%d\n%d\n",minn,maxx); 39 return 0; 40 }