区间DP -- 石子合并(朴素DP)

 
设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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值