動態規劃練習-環狀石子歸併+四邊形不等式優化
阿新 • • 發佈:2019-02-11
思路:環狀的直接在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]列舉即可。