P1880 [NOI1995]石子合并(环形区间)
和上一个题目相似,只不过这个变成了环形的,那么我们确定区间的时候就需要把长度变成2×n这样的话我们的集合才能包含所有的情况。
#include <bits/stdc++.h>
using namespace std;
const int N= 6e2 + 5 ;
int f[ N] [ N] , f1[ N] [ N] , a[ N] , sum[ N] ;
int main ( )
{
int n; cin>> n;
memset ( f, 0x3f3f3f3f , sizeof f) ;
memset ( f1, - 0x3f3f3f3f , sizeof f1) ;
for ( int i= 1 ; i<= n; i++ ) {
cin>> a[ i] ;
a[ i+ n] = a[ i] ;
}
for ( int i= 1 ; i<= n* 2 ; i++ ) sum[ i] = sum[ i- 1 ] + a[ i] ;
for ( int len= 1 ; len<= n; len++ ) {
for ( int l= 1 ; l+ len- 1 <= n* 2 ; l++ ) {
int r= len+ l- 1 ;
if ( len== 1 ) f[ l] [ r] = f1[ l] [ r] = 0 ;
for ( int k= l; k<= r; k++ ) {
f[ l] [ r] = min ( f[ l] [ r] , f[ l] [ k] + f[ k+ 1 ] [ r] + ( sum[ r] - sum[ l- 1 ] ) ) ;
f1[ l] [ r] = max ( f1[ l] [ r] , f1[ l] [ k] + f1[ k+ 1 ] [ r] + ( sum[ r] - sum[ l- 1 ] ) ) ;
}
}
}
int maxv= - 0x3f3f3f3f , minv= 0x3f3f3f3f ;
for ( int i= 1 ; i<= n; i++ ) {
maxv= max ( f1[ i] [ i+ n- 1 ] , maxv) ;
minv= min ( f[ i] [ i+ n- 1 ] , minv) ;
}
cout<< minv<< endl<< maxv<< endl;
}