問題描述:
給定一棵有向樹t,樹 t中每個頂點u都有乙個權 w(u);樹的每條邊(u,v)也都有乙個非負邊長 d(u,v)。 有向樹t的每個頂點 u 可以看作客戶, 其服務需求量為w(u)。 每條邊(u,v)的邊長 d(u,v) 可以看作運輸費用。如果在頂點u 處未設定服務機構,則將頂點u 處的服務需求沿有 向樹的邊(u,v)轉移到頂點v處服務機構需付出的服務轉移費用為w(u)*d(u,v)。樹根處已設定 了服務機構,現在要在樹t中增設 k處服務機構,使得整棵樹t 的服務轉移費用最小。
程式設計任務:
對於給定的有向樹t,程式設計計算在樹t中增設 k處服務機構的最小服務轉移費用。
資料輸入:
由檔案input.txt給出輸入資料。第1 行有 2個正整數n和 k。n表示有向樹t 的邊數;k是要增 設的服務機構數。有向樹t的頂點編號為0,1,…,n。根結點編號為 0。接下來的n行中, 每行有表示有向樹t的一條有向邊的 3個整數。第i+1行的 3 個整數 wi,vi,di分別表示編號為i 的頂點的權為wi,相應的有向邊為(i, vi),其邊長為di。
結果輸出:
將計算的最小服務轉移費用輸出到檔案output.txt。
樣例:4 2
1 0 1
1 1 10
10 2 5
1 2 3
核心思想:
f[i,j,k]=min 大概就這個意思,轉二叉然後樹型dp
type
tre=record
lc,rc:longint;
end;
var f:array[0..100,0..100,0..100]of longint;
d:array[0..100,0..100]of longint;
a:array[0..100]of longint;
tree:array[0..100]of tre;
k:longint;
function min(a,b:longint):longint;
begin
if a>b then exit(b);
exit(a);
end;
procedure init;
var i,j,x,y,p,n:longint;
begin
fillchar(f,sizeof(f),100);
fillchar(d,sizeof(d),10);
fillchar(tree,sizeof(tree),255);
fillchar(a,sizeof(a),0);
readln(n,k);
for i:=1 to n do
begin
readln(a[i],y,x);
if tree[y].lc=-1 then tree[y].lc:=i{}
else
begin
tree[i].rc:=tree[y].lc;
tree[y].lc:=i;
end;
d[i,y]:=x;
end;
for p:=0 to n do
begin
tot:=0;
if tree[t].lc>-1 then inc(tot,dp(tree[t].lc,t,i));
if tree[t].rc>-1 then inc(tot,dp(tree[t].rc,ad,k-i-1));
f[t,ad,k]:=min(f[t,ad,k],tot);
end;
exit(f[t,ad,k]);
end;
begin
assign(input,'p320.in');reset(input);
assign(output,'p320.out');rewrite(output);
init;
writeln(dp(0,0,k));
close(input);close(output);
end.
有向直線K中值問題(ksaw) 60分
演算法 treedp 分析 直接將3 21的模型套用過來,只有一點不同的是由原先的樹型變成了直線型,實際上變得更加簡單了,不用再分成兩棵子樹。在遞迴的時候直接加個判斷以防止跳出邊界就行了。program ksaw const maxn 1000 maxm 50 var n,m longint w a...
dp 最大k乘積問題
問題描述 設i是乙個 n位十進位制整數。如果將i劃分為 k段,則可得到k個整數。這k個整數的乘積稱為i 的乙個 k乘積。試設計乙個演算法,對於給定的 i和 k,求出 i的最大 k乘積。程式設計任務 對於給定的i和k,程式設計計算i的最大k 乘積。資料輸入 由檔案input.txt提供輸入資料。檔案的...
有向樹與樹的括號序列最小表示法
有向樹 乙個弱連通有向圖,若去掉方向後得到一棵樹,則稱此有向圖為一棵有向樹,記為t。外向樹 若乙個有向樹t,有且只有乙個頂點入度為0,其餘頂點入度都為1,則稱t為外向樹。t中入度為0的節點被稱為t的根節點,出度為0的節點被稱為t的葉節點。每個節點的有向邊指向的節點被稱為該節點的子節點。內向樹 若乙個...