【洛谷P1880】[NOI1995]石子合并

石子合并

 

fmax[l][r]表示合并区间[l,r]的最大分值,

fmin[l][r]表示合并区间[l,r]的最小分值

 

for(k l~r-1)

  fmax[l][r]=max(fmax[l][r],fmax[l][k]+f[k+1][r]+sum[l][r]);

sum[l][r]可以提到外面

 

最小值同理

 

处理环形就把环搞成一个2倍长度的链,最后枚举长度为n的区间最大得分和最小得分

 

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int MAXN = 1010 ;
 5 int a[MAXN],sum[MAXN],n,fmax[MAXN][MAXN],fmin[MAXN][MAXN];
 6 inline int read()
 7 {
 8     int x=0;char c=getchar();
 9     while(c<'0'||c>'9') c=getchar();
10     while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar();}
11     return x;
12 }
13 int main()
14 {
15     n=read();
16     for(register int i=1;i<=n;i++)
17     {
18         a[i]=read(); a[i+n]=a[i];
19     }
20     for(register int i=1;i<=(n<<1);i++)
21      sum[i]=sum[i-1]+a[i];
22     for(int i=1;i<=(n<<1);i++)
23      for(int j=1;j<=(n<<1);j++)
24       fmin[i][j]=0x7fffffff>>1;
25     for(int i=1;i<=n<<1;i++)
26      fmin[i][i]=0;
27     for(register int len=2;len<=n<<1;len++)
28      for(register int l=1;l+len-1<=n<<1;l++)
29      {
30          int r=l+len-1;
31         for(register int k=l;k<r;k++)
32         {
33             fmax[l][r]=max(fmax[l][r],fmax[l][k]+fmax[k+1][r]);
34             fmin[l][r]=min(fmin[l][r],fmin[l][k]+fmin[k+1][r]);
35         }
36         fmax[l][r]+=sum[r]-sum[l-1];
37         fmin[l][r]+=sum[r]-sum[l-1];
38      }
39     int ans1=0x7fffffff,ans2=0;
40     for(int i=1;i<=n;i++)
41     {
42         ans1=min(ans1,fmin[i][i+n-1]);
43         ans2=max(ans2,fmax[i][i+n-1]);
44     }
45     printf("%d\n%d\n",ans1,ans2);
46     return 0;
47 }

 

posted @ 2018-04-16 21:09  yjk  阅读(202)  评论(0编辑  收藏  举报