P1063 能量项链

 

 

输入输出样例

输入 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
4
2 3 5 10
输出 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
710

说明/提示

NOIP 2006 提高组 第一题

 

思路

  很像石子合并的一道题,只不过把获得的价值给改了一下。

  如果有两堆石子可以合并,分别为 ( i , k ) , ( k + 1, j ) ,获得的价值为 head [ i ] * tail [ k ] * tail [ j ]。

  然后像石子合并那样做就可以了。

 

CODE

 

#include  < bits/stdc++.h >
#define  dbg( x ) cout  <<  #x  <<  " = "  << x  << endl
#define  eps  1 e - 8
#define  pi  acos( - 1.0 )

using  namespace std ;
typedef  long  long LL ;

const  int inf  =  0x 3f3f3f3f ;

template < class T > inline  void  read(& res )
{
     char c ;T flag = 1 ;
     while((c = getchar()) < ' 0 ' ||c > ' 9 ' )if(c == ' - ' )flag =- 1 ;res =c - ' 0 ' ;
     while((c = getchar()) >= ' 0 ' &&c <= ' 9 ' )res =res * 10 +c - ' 0 ' ;res *=flag ;
}

namespace _buff  {
     const  size_t BUFF  =  1  <<  19 ;
     char  ibuf [BUFF ],  *ib  = ibuf ,  *ie  = ibuf ;
     char  getc()  {
         if  (ib  == ie )  {
            ib  = ibuf ;
            ie  = ibuf  +  fread(ibuf ,  1 , BUFF , stdin );
         }
         return ib  == ie  ?  - 1  :  *ib ++ ;
     }
}

int  qread()  {
     using  namespace _buff ;
     int ret  =  0 ;
     bool pos  =  true ;
     char c  =  getc();
     for  (;  (<  ' 0 '  || c  >  ' 9 ' )  && c  !=  ' - ' ; c  =  getc())  {
         assert( ~c );
     }
     if  (==  ' - ' )  {
        pos  =  false ;
        c  =  getc();
     }
     for  (; c  >=  ' 0 '  && c  <=  ' 9 ' ; c  =  getc())  {
        ret  =  (ret  <<  3 )  +  (ret  <<  1 )  +  (^  48 );
     }
     return pos  ? ret  :  -ret ;
}

const  int maxn  =  307 ;

int n ;

int  head [maxn ];
int  tail [maxn ];
int  f [maxn ][maxn ];

int  main()
{
     read(n );
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         read( head [i ]);
         head [+ i ]  =  head [i ];
     }
     for  (  int i  =  1 ; i  <=  2  * n  -  1 ;  ++)  {
         tail [i ]  =  head [+  1 ];
     }
     int ans  =  - 1 ;
     tail [ 2  * n ]  =  head [ 1 ];
     for  (  int z  =  1 ; z  <= n  -  1 ;  ++)  { //!枚举区间长度
         for  (  int i  =  1 ; i  <=  2  * n  - z ;  ++)  {
             int j  = i  + z ;
             for  (  int k  = i ; k  <= j  -  1 ;  ++)  {
                 f [i ][j ]  =  max( f [i ][j ],  f [i ][k ]  +  f [+  1 ][j ]  +  head [i ]  *  tail [k ]  *  tail [j ]);
                ans  =  max(ans ,  f [i ][j ]);
             }
         }
     }
    cout  << ans  << endl ;
     return  0 ;
}