环形石子合并【n^2做法】

题目链接:https://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/1977.html

 

四边形不等式优化dp

学习博客:https://blog.csdn.net/noiau/article/details/72514812

环形排列 N 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的 2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。求 N 堆石子合并成一堆的最小得分。

 

(其实还有NlogN的做法)

#include 
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define mp make_pair
#define pb push_back
#define ls (o<<1)
#define rs (o<<1|1)
#define ll long long
using namespace std;
const int N = 10010;
int n,m,s[N],dp[N][N],sum[N],pos[N][N];
int oper;
int main() {
   // freopen("a.txt","r",stdin);
    ios::sync_with_stdio(0);
    cin>>n;
    rep(i, 1, n) cin>>s[i];
    rep(i, n+1, 2*n) s[i] = s[i-n];
    rep(i, 1, 2*n) sum[i] = sum[i-1] + s[i];
    n*=2;

    rep(i, 1, n) dp[i][i] = 0,pos[i][i] = i;
    per(i, n, 1)
        rep(j, i+1, n) {
            int ans = 1e9;
            int mk = -1;
            rep(k, pos[i][j-1],pos[i+1][j]) {
                if(ans > dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) {
                    ans = dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
                    mk = k;
                }
            }
            dp[i][j] = ans;
            pos[i][j] = mk;
        }
    int ans = 1e9;
    rep(i, 1, n/2) ans = min(ans,dp[i][i+n/2-1]);
    cout<

 

你可能感兴趣的:(stut,oj,动态规划)