1. 程式人生 > >動態規劃練習-環狀石子歸併+四邊形不等式優化

動態規劃練習-環狀石子歸併+四邊形不等式優化

這裡寫圖片描述

思路:環狀的直接在n後面加上a[0]-a[n]變成鏈狀即可。
這題範圍小,如果n<1000,則必須四邊形不等式優化降低複雜度為O(n^2)
Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 4e2+6;
int dp[AX][AX];
int a[AX];
int s[AX][AX];
int sum[AX];
int n ;

int main(){
    scanf("%d",&n);
    sum[0] = 0;
    for( int
i = 1 ; i <= n ; i++ ){ scanf("%d",&a[i]); sum[i] = sum[i-1] + a[i] ; } for( int i = n + 1 ; i <= 2 * n ; i++ ){ sum[i] = sum[i-1] + a[i-n]; } for( int i = 1 ; i <= 2 * n ; i++ ){ dp[i][i] = 0; s[i][i] = i; } for( int r = 2
; r <= n ; r++ ){ for( int i = 0 ; i + r - 1 <= 2 * n ; i++ ){ int j = i + r - 1 ; dp[i][j] = INF; int tmp = sum[j] - sum[i-1] ; for( int k = s[i][j-1] ; k <= s[i+1][j] ; k++ ){ //dp[i][j] = min( dp[i][j] , dp[i][k] + dp[k+1][j] + tmp );
if( dp[i][j] > dp[i][k] + dp[k+1][j] + tmp ){ dp[i][j] = dp[i][k] + dp[k+1][j] + tmp; s[i][j] = k ; } } } } int res = INF; for( int i = 1 ; i <= n ; i++ ){ res = min( res , dp[i][i+n-1] ) ; } printf("%d\n",res); return 0 ; }

應用:
s[i][j]記錄dp[i][j]取得最優解的k,每次只需要將k從s[i][j-1] 到 s[i+1][j]列舉即可。