ICPC2017Beijing J Panguとストーンズ(ブロンズタイトル)

問題

中国の神話では、Panguは、最初の生き物と空と大地の生みの親です。彼は卵から目覚めた2つの部分に卵を分割:空と大地。

初めに、唯一の石のすべての土地の上に、地球上の山ありませんでした。

N. Panguは素晴らしい山を構築するために、1つの山にそれらのすべてをマージしたかっに1から番号石のN山がありました。いくつかの山の石の合計がSだった場合、Panguは1つの山にそれらを山積みするS秒を必要とし、新しい山にS石が存在することになります。

残念ながら、毎回Panguは、唯一の山に連続した山をマージすることができます。そして彼は合併山の数がRよりもL未満または大きくてはなりません

Panguは、できるだけ早くこれを終了したいと考えていました。

あなたは彼を助けることはできますか?何の解決策がなかった場合は、「0」を答える必要があります。

入力

複数のテストケースがあります。

それぞれの場合の最初の行は、N、L、Rは上記3つの整数を含む(2 <= N <= 100,2 <= L <= R <= N)。

それぞれの場合の2行目は、N個の整数A1を含有する、A2 ... AN(1 <=は、<= 1000、I = 1 ... N AI)パイル1、パイル2の石の数を示す、...パイルN.

テストケースの数が110未満であり、N> = 50で最大で5テストケースがあります。

出力

各テストケースについて、あなたは出力最小時間(秒単位)Panguは取らなければならなかったはずです。Panguは彼の仕事をすることが不可能だった場合は、出力0必要があります。

溶液

石の合併は、それぞれがいくつかの隣接ヒープ、合併のコストや石の数をマージ、各番号は、結合ヒープ上限値と下限値、最小コストを見つけることを有しています。
DP [I] [J] [ k]はiがJにマージ、kはスタックの最小コストに分割されている意味します。
計算する列挙インターバル長、特定の間隔、分割列挙子スタック、特定の列挙分割方法を列挙する。
DP [I] [J] [ K] =分(DP [I] [J] [K]、DP [I] [C] [K-1] + DP [C + 1] [j] [1]) ;
その後、パイルにマージ、適格分割ヒープおよび特定の方法を列挙する。
DP [I] [J] [ 1] =分(DP [I] [J] [1]、DP [I] [C] [K] + DP [C + 1] [j] [1] +和[ J] -sum [I-1] )。

コード

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstring>
#define ll long long
#define ioss ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
using namespace std;
const int N = 110;
const int INF = 0x3f3f3f3f;
int dp[N][N][N], s[N], sum[N];
int n,l,r;
int main(){
    ioss;
    //freopen("51nod_1880_5_in.txt","r",stdin);
    //freopen("ans.out","w",stdout);
    while(cin>>n>>l>>r){
        memset(dp,0x3f,sizeof(dp));
        for(int i=1;i<=n;i++){
            cin>>s[i];
            sum[i]=sum[i-1]+s[i];
            dp[i][i][1]=0;
        }
        for(int len=2;len<=n;len++){
            for(int i=1;i+len-1<=n;i++){
                int j=i+len-1;
                for(int k=2;k<=min(len,r);k++){
                    for(int c=i+k-2;c<j;c++){
                        dp[i][j][k]=min(dp[i][j][k],dp[i][c][k-1]+dp[c+1][j][1]);
                    }
                }
                for(int k=l-1;k<=r-1;k++){
                    for(int c=i+k-2;c<j;c++){
                        dp[i][j][1]=min(dp[i][j][1],dp[i][c][k]+dp[c+1][j][1]+sum[j]-sum[i-1]);
                    }
                }
            }
        }
        cout<<(dp[1][n][1]==INF?0:dp[1][n][1])<<endl;
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/sz-wcc/p/11426504.html