[NOI2002]貪欲9匹の龍

[NOI2002]貪欲9匹の龍

トピックの背景

9匹の龍の伝説は、特に貪欲な動物です。それは9頭が生まれ、育っの過程で、それは社長の新しいヘッドの多くが時々ありました場合にのみ、名前「9匹の龍」が、しかし、総数はナインの頭よりもはるかに大きくなり、当然のことながら、そこになります経年による自分自身オフ古いヘッド。

タイトル説明

ある日は、9匹の龍のMヘッドがあれば、すべてを食べに1を待って、大喜び、Nの果物の果樹園を見てきましたがあります。それは、N個の果実のM個のグループに分割する必要があるのでしかし、各ヘッドは、各ヘッド群が食べるようにそれぞれ、少なくとも一つの果実を有する、世話をしなければなりません。

MヘッドはKに「ビッグ」と呼ばれる最大値は、すべてのヘッドの最初で、果物を食べるためにKにたまたま持っており、果物当然唯一最大の果実のを含める必要があります。N-1は、全果実以来、果実は他の果物のいずれかに「行く」に沿って枝のいずれかからなることができ、アップ小枝フルーツによって接続されています。

2つの果実はヘッドを食べている場合、その後、それが異なるヘッドによって食べ2個の果実を必要とするように接続されている場合小枝の各部分のために、2つが共同枝が果実を分離するために壊したと向かいます頭が壊れた枝と一緒に、果物に直接それを取ると一緒に食べるのが面倒になります。もちろん、枝を食べることは非常に快適ではないので、9つの龍不快な値は、ヘッドのすべてのブランチの「不快な値」であると食べながら、それぞれの作品は「不快な値」食べるために支店を持っています。

九匹の龍はそれが可能な限り小さく「不快値」願っています、それはあなたがそれを計算することができますか?

例えば、図1に示す例では、それは、8本の果物の木、枝セグメント7、各セグメントが次の分岐枝にマークされているの「SAD値」を含みます。2頭と九匹の龍は、4つのバルクは最大の果物を含める必要があり、果物を食べる必要があります。すなわち、N = 8、M = 2、K = 4:

図1は、図IIは、最適な戦略を説明し、果実の形状を記述する。

入力形式

三つの整数N(1 <= N <= 300)、M(2 <= M <= N)、K(1 <= K <= N)の最初の行を含む入力ファイルDragon.in。N番号順次果実1,2、...、N、および最大数は常に1つの果実です。ラインNへのライン2は、形状果樹を説明、各ラインは、三つの整数(1 <= A <= N)、B(1 <= bの<= N)、C(0 <= C <=)を含有します^一部の値cについて不快の存在を示す$ 5 $ 10は、果物やフルーツ分岐接続bです。

出力フォーマット

出力ファイルのDragon.out一つだけの行は、「大きな」要件、9匹の不快な龍の最小値を満たすために前提を表す整数が含まれています。要件、-1の出力を満たしていない場合。

サンプル入力と出力

入力#1
8 2 4 
1 2 20 
1 3 4 
1 4 13 
2 5 10 
2 6 12 
3 7 15 
3 8 5
出力#1
4

説明/ヒント

サンプル説明の例では、タイトルに対応します。

問題の解決策

どこで何の解決策は、場合にのみ解決せず、<M-1 NK場合は、明らかではありません。

解決するために、動的プログラミングを使用することを検討してください。

まず、M = 2、唯一の2例があり、この質問を観察することによってMを見つけて、M> 2

M> 2の場合には、交換を介して各ヘッドは、少なくとも一つの小さなヘッドを有するような構成を有し、果物を食べなければならない隣接する果物を食べないであろう。

あなただけの果実は二つの状態の合計の大部分を食べることであるかどうかを検討する必要があります。M = 2の場合、それは果物を食べるために、隣接する小さなヘッドのコストをカウントしなければなりません。

その後、毎日のルーチンは、聞かせて\(F [U] [J ] \) で表される(U \)\サブツリーため\(Jの\)最小コストを食べるの大部分で、それは不可能を決定することが見出さ二点間のすべてのかどうかバルクは、次に一次元追加、食べられる\を(F [U] [J ] [0/1] \) を表し\(U \)食べられるかどうかをドットバルク。

次いでDP式は
\ [F [U] [j ] [0] = \分(F [U] [j] [0]、\分([V] [T] [0] + F F [U] [ JT] [0] + [M = 2] * E [I] .W、[V] [T] F [1] + F [U] [JT] [0]))\\ F [U] [J ] [1] = \分( F [U] [J] [1]、\分(F [v] [T] [1] + F [U]は[JT] [1] + E [I] .W 、[V] [T] F
[0] + F [U] [JT] [1]))\] 実際には私たちも、サンプルが)(厄介なされていなかったことを見つけるために、次に驚い

だから、再検討方程式DPへ

我々はそれ以外の場合は(もちろん、Nが小さい場合、その後、実際には効果なし)にDP値fにますます小さくなり、バックダウン前のF DP配列の前に必要とするたびに

だから我々は、tmpに[J] [0/1] Fを保存するために[u]が配列の場合、ACは楽しいことができます

時間複雑\(O(N ^ 3)\)

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T>T read(){
    T x=0,w=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*w;
}
template<class T>T read(T&x){
    return x=read<T>();
}
using namespace std;

co int N=301;
int n,m,k;
int f[N][N][2],tmp[N][2];
vector<pair<int,int> > e[N];

void dfs(int x,int fa){
    f[x][0][0]=f[x][1][1]=0;
    for(unsigned i=0;i<e[x].size();++i){
        int y=e[x][i].first,w=e[x][i].second;
        if(y==fa) continue;
        dfs(y,x);
        memcpy(tmp,f[x],sizeof tmp),memset(f[x],0x3f,sizeof f[x]);
        for(int j=0;j<=k;++j)
            for(int t=0;t<=j;++t){
                f[x][j][0]=min(f[x][j][0],min(f[y][t][0]+tmp[j-t][0]+(m==2)*w,f[y][t][1]+tmp[j-t][0]));
                f[x][j][1]=min(f[x][j][1],min(f[y][t][1]+tmp[j-t][1]+w,f[y][t][0]+tmp[j-t][1]));
            }
    }
}
int main(){
    read(n),read(m),read(k);
    if(n-k<m-1) return puts("-1"),0;
    for(int i=1,x,y,w;i<n;++i){
        read(x),read(y),read(w);
        e[x].push_back(make_pair(y,w)),e[y].push_back(make_pair(x,w));
    }
    memset(f,0x3f,sizeof f);
    dfs(1,1);
    printf("%d\n",f[1][k][1]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/autoint/p/11242146.html