设Num[i][j]表示从第i堆到第j堆石子数总和。
DPMax[i][j]表示将从第i堆石子合并到第j堆石子的最大的得分
DPMax[i][j] = max( DPMax[i][j], DPMax[i][k] + DPMax[k + 1][j] + Num[i][j] );
时间复杂度:O(n^3)
优化:四边形优化,GarsiaWachs
#include <iostream>
#include <cstring>
#include <climits>
using namespace std;
#define SIZE 100
int Stone[SIZE];
int Num[SIZE][SIZE];
int DPMax[SIZE][SIZE];
int lenOfStone;
int twiceLen;
void init(){
memset( Stone, 0, sizeof( Stone ) );
memset( Num, 0, sizeof( Num ) );
memset( DPMax, 0, sizeof( DPMax ) );
}
void getNum(){
for( int i = 1; i <= twiceLen; ++i )
Num[i][i] = Stone[i];
for( int dist = 1; dist <= lenOfStone - 1; ++ dist ){
for( int start = 1; start <= lenOfStone && start + dist <= twiceLen; ++start ){
const int end = start + dist;
const int mid = ( end + start ) / 2;
Num[start][end] = Num[start][mid] + Num[mid + 1][end];
}
}
}
void getDP(){
for( int i = 1; i <= twiceLen; ++i )
DPMax[i][i] = 0;
for( int dist = 1; dist <= lenOfStone - 1; ++dist ){
for( int start = 1; start <= lenOfStone && start + dist <= twiceLen; ++start ){
const int end = start + dist;
for( int mergePos = start; mergePos < end; ++mergePos ){
DPMax[start][end] = max( DPMax[start][end], DPMax[start][mergePos] + DPMax[mergePos + 1][end] + Num[start][end] );
}
}
}
int max = INT_MIN;
for( int i = 1; i <= twiceLen; ++i ){
for( int j = 1; j <= twiceLen; ++j ){
if( max < DPMax[i][j] )
max = DPMax[i][j];
}
}
cout << max << endl;
}
int main(){
while( 1 ){
init();
cin >> lenOfStone;
if(lenOfStone == 0)
break;
twiceLen = 2 * lenOfStone - 1;
for( int i = 1; i <= lenOfStone; ++i )
cin>>Stone[i];
for( int i = lenOfStone + 1; i <= twiceLen; ++i )
Stone[i] = Stone[i - lenOfStone];
getNum();
getDP();
}
return 0;
}