環形石子合併【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 <bits/stdc++.h>
#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<<ans;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章