区间dp学习笔记
定义
令状态\(f(i, j)\)表示将下标位置\(i\)到\(j\)的所有元素合并能获得的价值的最大值,那么\(f(i, j) = max(f(i, k) + f(k+1, j) + cost)\), \(cost\)为将这两组元素合并起来的代价。
性质
区间DP有以下特点:
合并:即将两个或多个部分进行整合
特征:能将问题分解为能两两合并的形式
求解:对整个问题设最优值,枚举合并点,将问题分为左右两部分,最后合并两个部分的最优值得到原问题的最优值。
例题
代码
#include <bits/stdc++.h>
#define i64 long long
using namespace std;
const int MAXN = 505 ;
int n ;
i64 a[MAXN] ;
i64 dp[MAXN][MAXN][5] ;
i64 sum[MAXN] ;
int main()
{
cin >> n ;
for(int i = 1 ; i <= n ; i ++ ) {cin >> a[i] ; a[i + n] = a[i] ;}
for(int i = 1 ; i <= 2 * n ; i ++ ) sum[i] = sum[i - 1] + a[i] ;
for(int i = 1 ; i <= 2 * n ; i ++ ) dp[i][i][2] = 0 , dp[i][i][1] = 0 ;
for(int len = 2 ; len <= n ; len ++ )
{
for(int i = 1 ; i <= 2*n - len + 1 ; i ++ )
{
int j = len + i - 1 ;
dp[i][j][2] = 0x3f3f3f ;
for(int k = i ; k < j ; k ++ )
{
dp[i][j][1] = max(dp[i][j][1], dp[i][k][1] + dp[k + 1][j][1] + sum[j] - sum[i - 1]) ;
dp[i][j][2] = min(dp[i][j][2], dp[i][k][2] + dp[k + 1][j][2] + sum[j] - sum[i - 1]) ;
}
}
}
i64 ans1 = 0 ;
i64 ans2 = 0x3f3f3f ;
for(int i = 1 ; i <= n ; i ++ )
{
ans1 = max(ans1, dp[i][i + n - 1][1]) ;
ans2 = min(ans2, dp[i][i + n - 1][2]) ;
}
cout << ans2 << endl ;
cout << ans1 << endl ;
return 0 ;
}

浙公网安备 33010602011771号