洛谷 P1180 石子合并 - 区间DP

洛谷 P1180 石子合并

题目传送门

区间DP模板题,枚举起点终点、中间点再进行转移即可。

方程为

 

这里我们可以使用前缀和来维护区间查和

值得注意的是,这里的石子围成一圈,我们可以把一个圈拆成两条链处理。

最后只需遍历dp(i,i+n-1)即可

#include<cstdio>
#define maxn 210
#include<algorithm>
#include<cstring>
using namespace std;
int num[maxn];
int sum[maxn];
int mx[maxn][maxn];
int mn[maxn][maxn];
int main()
{
   int n;
   memset(mn,0x3f,sizeof(mn));
   scanf("%d",&n);
   for(int i=1;i<=n;i++)
  {
       scanf("%d",&num[i]);  
       mn[i][i] = mn[i+n][i+n] = 0;
       num[i+n]=num[i];
  }
   for(int i=1;i<=2*n;i++)
  {
       sum[i] = sum[i-1] + num[i];
  }
   int mm=1000000,xx=0;
   for(int p=1;p<n;p++)
  {
       for(int i=1,j=i+p;(i<2*n)&&(j<2*n);i++,j=i+p)
      {
           for(int k=i;k<j;k++)
          {
               mx[i][j] = max(mx[i][j],mx[i][k]+mx[k+1][j]+sum[j]-sum[i-1]);
               mn[i][j] = min(mn[i][j],mn[i][k]+mn[k+1][j]+sum[j]-sum[i-1]);
          }
      }
  }
   for(int i=1;i<=n;i++)
  {
       xx=max(xx,mx[i][i+n-1]);
       mm=min(mm,mn[i][i+n-1]);

  }
   printf("%d\n%d",mm,xx);
}
posted @ 2020-10-13 16:11  岚默笙  阅读(163)  评论(0编辑  收藏  举报