[vijos P1518] [tyvj P1506] 河流

背景
安徽省蕪湖市集訓隊練習題
IOI 2005 Rivers(riv)
Description:Amber
Data:Official
Program:JackDavid127

描述
幾乎整個Byteland 王國都被森林和河流所覆蓋。小點的河匯聚到一起,形成了稍大點的河。就這樣,所有的河水都匯聚並流進了一條大河,最後這條大河流進了大海。這條大河的入海口處有一個村莊——Bytetown。
在Byteland國,有n個伐木的村莊,這些村莊都座落在河邊。目前在Bytetown,有一個巨大的伐木場,它處理着全國砍下的所有木料。木料被砍下後,順着河流而被運到Bytetown的伐木場。Byteland 的國王決定,爲了減少運輸木料的費用,再額外地建造k個伐木場。這k個伐木場將被建在其他村莊裏。這些伐木場建造後,木料就不用都被送到Bytetown了,它們可以在 運輸過程中第一個碰到的新伐木場被處理。顯然,如果伐木場座落的那個村子就不用再付運送木料的費用了。它們可以直接被本村的伐木場處理。
注:所有的河流都不會分叉,形成一棵樹,根結點是Bytetown。
國王的大臣計算出了每個村子每年要產多少木料,你的任務是決定在哪些村子建設伐木場能獲得最小的運費。其中運費的計算方法爲:每一噸木料每千米1分錢。
編一個程序: 
1.從文件讀入村子的個數,另外要建設的伐木場的數目,每年每個村子產的木料的塊數以及河流的描述。 
2.計算最小的運費並輸出。

格式
輸入格式

第一行包括兩個數n(2<=n<=100),k(1<=k<=50,且k<=n)。n爲村莊數,k爲要建的伐木場的數目。除了Bytetown 外,每個村子依次被命名爲 1,2,3……n,Bytetown被命名爲0。
接下來n行,每行3個整數:
wi——每年 i 村子產的木料的塊數。(0<=wi<=10000) 
vi——離 i 村子下游最近的村子。(即 i 村子的父結點)(0<=vi<=n) 
di——vi 到 i 的距離(千米)。(1<=di<=10000) 
保證每年所有的木料流到bytetown 的運費不超過2000,000,000分 
50%的數據中n不超過20。
輸出格式

輸出最小花費,精確到分。
樣例1
樣例輸入1[複製]
4 2 
1 0 1 
1 1 10 
10 2 5 
1 2 3 
樣例輸出1[複製]
4

提示
樹形動態規劃
經典問題
來源
安徽省蕪湖市集訓隊練習題
IOI 2005 Rivers(riv)
Description:Amber
Data:Official
Program:JackDavid127

首先多叉轉二叉,lch爲真兒子,rch爲兄弟;
記憶化dfs(root,groot,kk,s) 表示以root爲根,最近的有伐木場的祖先爲groot,且root的子孫們(不算自己)建造kk個伐木場的最優解。s表示的是root的父節點距離groot的距離,而不是root距groot的距離(參照多叉轉二叉,因爲若s表示的是root到groot的距離的話,其rch即兄弟節點到groot的距離就無法表示。)本程序中cout<

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int fa[111],len[111],a[111],lch[111],rch[111];
int f[111][111][111];
int n,k,h,t;
int dfs(int root,int groot,int kk,int s)
{
    if(root==-1||groot==-1) return 0;
    if(f[root][groot][kk]!=2139062143) return f[root][groot][kk];
    int &now=f[root][groot][kk];
    for(int i=0;i<=kk;i++) // root這個點不放伐木場
        now=min(now,dfs(lch[root],groot,i,s+len[root])+dfs(rch[root],groot,kk-i,s)+(s+len[root])*a[root]);
    for(int i=0;i<kk;i++)//放   伐木場
        now=min(now,dfs(lch[root],root,i,0)+dfs(rch[root],groot,kk-1-i,s));
    return f[root][groot][kk];
}

int main()
{
    memset(rch,-1,sizeof(rch));
    memset(lch,-1,sizeof(lch));
    memset(f,127,sizeof(f));
    //cout<<f[1][1][1]<<endl;// 2139062143
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i]>>fa[i]>>len[i];
        rch[i]=lch[fa[i]];
        lch[fa[i]]=i;
    }
    // cout<<' '<<rch[0]<<endl;
    cout<<dfs(0,0,k,0)<<endl;
    //cout<<dfs(lch[0],0,k,0)<<endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章