区间DP

DP分析:

  1. 集合:将区间看作一堆方案的集合
  2. 属性:每个子集取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;
}


900. 整数划分 - AcWing题库

posted @ 2025-11-24 14:59  Glosie  阅读(7)  评论(0)    收藏  举报