[作业]警卫安排

来源:互联网 发布:360云盘网络连接失败 编辑:程序博客网 时间:2024/04/30 03:50
警卫安排(security.pas/c/cpp)
一个重要的基地被分为n 个连通的区域。出于某种神秘的原因,这些区域以一个区域为
核心,呈一颗树形分布。 
在每个区域安排警卫所需要的费用是不同的,而每个区域的警卫都可以望见其相邻的区
域,只要一个区域被一个警卫望见或者是安排有警卫,这个区域就是安全的。你的任务是:
在确保所有区域都是安全的情况下,找到安排警卫的最小费用。 
 
输入数据     
  第一行n,表示树中结点的数目。 
  接下来的 n 行描述了 n 个区域的信息,每一行包含的整数依次为:区域的标号
i(0<i<=n),在区域i 安排警卫的费用k,区域i 的子结点数目m,接下来m 个数为区域i
的子结点编号。 
 
输出数据     
  一行一个整数,为最小的安排费用。 
 
样例输入与输出     

1 30 3 2 3 4 
2 16 2 5 6 
3 5 0 
4 4 0 
5 11 0 
6 5 0 
25 
 
数据范围     

  对于所有的数据,0<n<=720。 
-------------------------------------------------------------------------------------------------------------------
很经典的树状DP。
-------------------------------------------------------------------------------------------------------------------
代码:

type    link=^node;    node=record x:longint; next:link; end;var   cost:array[1..720] of longint;   v:array[1..720] of boolean;   g:array[1..720] of link;   dp:array[1..720,1..3] of longint;   n:longint;procedure connect(a,b:longint);var   p:link;begin     new(p);     p^.x:=b;     p^.next:=g[a];     g[a]:=p;end;function min(a,b:longint):longint;begin     if a<b then exit(a) else exit(b);end;function f(x,k:longint):longint;var   p:link;   sum:longint;begin     if dp[x,k]=-1 then begin        if k=1 then begin//x安放保安           p:=g[x];           dp[x,k]:=cost[x];           while p<>nil do begin                 inc(dp[x,k],min(f(p^.x,1),f(p^.x,2)));                 p:=p^.next;           end;        end;        if k=2 then begin//x被父节点看到,x不放           dp[x,k]:=0;           p:=g[x];           while p<>nil do begin                 inc(dp[x,k],min(f(p^.x,1),f(p^.x,3)));                 p:=p^.next;           end;        end;        if k=3 then begin//x被子节点看到,x不放           sum:=0;           p:=g[x];           while p<>nil do begin                 inc(sum,min(f(p^.x,1),f(p^.x,3)));                 p:=p^.next;           end;           dp[x,k]:=maxlongint;           p:=g[x];           while p<>nil do begin                 dp[x,k]:=min(dp[x,k],sum-min(f(p^.x,1),f(p^.x,3))+f(p^.x,1));                 p:=p^.next;           end;        end;     end;     f:=dp[x,k];end;procedure main;var   i,j,k,m,x:longint;begin     readln(n);     fillchar(v,sizeof(v),true);     for j:=1 to n do begin         read(i);         read(cost[i]);         read(m);         for k:=1 to m do begin             read(x);             v[x]:=false;             connect(i,x);         end;     end;     for i:=1 to n do     for j:=1 to 3 do         dp[i,j]:=-1;     for i:=1 to n do         if v[i] then begin            write(min(f(i,1),f(i,3)));            break;         end;end;begin     assign(input,'security.in');     assign(output,'security.out');     reset(input);     rewrite(output);     main;     close(input);     close(output);end.



原创粉丝点击