区间DP
DP分析:
- 集合:将区间看作一堆方案的集合
- 属性:每个子集取min或max就得到整个集合的min或max
P1005 [NOIP 2007 提高组] 矩阵取数游戏 - 洛谷
区间DP + 高精度
const int N = 1e2;
__int128 f[N][N], ans; // 区间DP:f[j][k]表示在区间[j,k]内能获得的最大价值
int a[N];
void hp(__int128 x){
//if(x < 0) putchar('-'), x = -x;
if(x >= 10)hp(x / 10);
putchar(x % 10 + '0');
}
void solve(){
int n, m; cin >> n >> m;
per(i, 1, n){
per(j, 1, m)cin >> a[j];
f[1][m] = 0;
per(j, 1, m)
rep(k, m, j - 1)
f[j][k] = max(f[j - 1][k] + a[j - 1] * (__int128(1) << (j - 1 + m - k)), f[j][k + 1] + a[k + 1] * (__int128(1) << (j - 1 + m - k)));
__int128 res = 0;
per(j, 1, m)res = max(res, f[j][j - 1]);
ans += res;
}
hp(ans);//无法cout超过long long的数,要用高精度输出
}
282. 石子合并 - AcWing题库
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
#define vi vector<int>
const int N = 3e2 + 5, inf = 0x3f3f3f3f;
int f[N][N];
void solve() {
int n; cin >> n; vi s(n + 1);
for(int i = 1; i <= n; ++i)cin >> s[i], s[i] += s[i - 1];
for(int len = 2; len <= n; ++ len){
for(int l = 1; l <= n - len + 1; ++l){
int r = l + len - 1; f[l][r] = inf;
for(int j = l; j < r; ++ j)//每个单词合并的代价就是区间和
f[l][r] = min(f[l][r], f[l][j] + f[j + 1][r] + s[r] - s[l - 1]);
//对l r区间不断地进行划分枚举
}
}
cout << f[1][n] << endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while(T--) solve();
return 0;
}

浙公网安备 33010602011771号