/ Vijos / 题库 / 选课 /

题解

151 条题解

  • 0
    @ 2009-10-27 20:06:31

    感谢LX神牛的多叉树转二叉树的思想,这次noip我有预感...

  • 0
    @ 2009-10-27 19:43:31

    多叉树转二叉树的作用:使得对于每个子树,左孩子是实际该父亲的左孩子,右孩子是该父亲的同辈。

    过程:

    {

    readln(dad,w[i]);

    right[i]:=left[dad];

    left[dad]:=i;

    }

    利用树形DP

    F表示以i为根的树分配j个课程能得到的最大学分

    显然F:=MAX(F[right[i],j],

    F[left[i],k]+F[right[i],j-k-1]+Value[i])

    时间复杂度O(MN^2)

  • 0
    @ 2009-10-26 19:09:01

    用取多数塔的方法貌似勉强能过。但太麻烦-,-去看树状DP。。。

  • 0
    @ 2009-10-24 22:55:35

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    type

    aa=record

    da,l,r:integer;

    end;

    var

    a:array[0..300]of aa;

    f:array[0..300,0..300]of integer;

    m,n,i,j,k,fa:integer;

    function find(x:integer):integer;

    begin

    if a[x].r=0 then exit(x)

    else exit(find(a[x].r));

    end;

    function max(a,b:integer):integer;

    begin

    if a>b then exit(a)

    else exit(b);

    end;

    function work(fa,k:integer):integer;

    var

    now,i:integer;

    begin

    if fa=0 then exit(0);

    if f[fa,k]>=0 then exit(f[fa,k]);

    now:=0;

    for i:=0 to k-1 do

    now:=max(now,(work(a[fa].l,i)+work(a[fa].r,k-i-1)+a[fa].da));

    now:=max(now,work(a[fa].r,k));

    f[fa,k]:=now;exit(now);

    end;

    begin

    readln(n,m);

    fillchar(f,sizeof(f),128);

    for i:=1 to n do

    begin

    readln(fa,a[i].da);

    if a[fa].l=0 then a[fa].l:=i

    else a[find(a[fa].l)].r:=i;

    f:=0;

    end;

    write(work(a[0].l,m));

    end.

    AC的第一个树形DP 秒杀O(∩_∩)O哈!

  • 0
    @ 2009-10-24 11:10:57

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 119ms

    ├ 测试数据 05:答案正确... 228ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:347ms

    type

    tree=record

    l,r,k:longint;

    end;

    var i,j,k,n,m,l:longint;

    a:array[0..301] of tree;

    f:array[0..301] of longint;

    b:array[-10..301,-10..301] of longint;

    function max(a,b:longint):longint;

    begin

    if a>b then max:=a

    else max:=b;

    end;

    procedure try(x,y:longint);

    var i,j,k,l:longint;

    begin

    if b[x,y]>=0 then exit;

    try(a[x].r,y);

    b[x,y]:=b[a[x].r,y];

    for k:=1 to y do

    begin

    try(a[x].l,k-1);

    try(a[x].r,y-k);

    b[x,y]:=max(b[x,y],b[a[x].l,k-1]+b[a[x].r,y-k]+a[x].k);

    end;

    end;

    begin

    read(n,m);

    for i:=1 to n do

    begin a[i].l:=-1;a[i].r:=-1;a[i].k:=-1;end;

    for i:=1 to n do

    begin

    read(k,l);

    readln;

    a[i].k:=l;

    if f[k]=0 then a[k].l:=i

    else a[f[k]].r:=i;

    f[k]:=i;

    end;

    for i:=-1 to n do

    for j:=-1 to m do

    if (i=-1) or (j=0) then b:=0 else b:=-1;

    try(a[0].l,m);

    writeln(b[a[0].l,m]);

    end.

  • 0
    @ 2009-10-23 20:53:31

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 41ms

    ├ 测试数据 05:答案正确... 119ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:160ms

    这个是sunny慢还是我写挂了...

  • 0
    @ 2009-10-17 22:22:44

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    打错一个地方,调了一个半小时,无语。

    不过还好终于赶上了:第1200个AC

    Flag   Accepted

    题号   P1180

    类型(?)   动态规划

    通过   1200人

    提交   2987次

    通过率   40%

    难度   2

  • 0
    @ 2009-10-15 20:10:44

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    交了n次 终于过了

    每个泛化物品只能取其中一个值

    因此要将泛化物品值的循环写在枚举体积的循环的内层

  • 0
    @ 2009-10-14 21:12:49

    好简单的递归求树形动归(背包合并)啊,竟然有这么多小粗心,有罪啊!!

    巧妙的利用函数进行递归,大家自己体会吧

    var n,m,i,j,r,q,k:longint;

    a,f:array[0..500,1..500] of longint;

    p,l,fu:array[0..500] of longint;

    function dfs(r:longint):longint;

    var s,j,i,k,er:longint;

    begin

    dfs:=1; f[r,1]:=p[r];

    for i:=1 to l[r] do

    begin

    er:=a[r,i]; s:=dfs(er);

    for j:=dfs downto 1 do

    for k:=1 to s do if f[r,j]+f[er,k]>f[r,j+k] then f[r,j+k]:=f[r,j]+f[er,k];

    inc(dfs,s);

    end;

    end;

    begin

    readln(n,m);

    for i:=1 to n do

    begin

    readln(r,p[i]); fu[i]:=r;

    inc(l[r]); a[r,l[r]]:=i;

    end;

    dfs(0);

    writeln(f[0,m+1]);

    end.

  • 0
    @ 2009-10-12 20:39:11

    经典的动态

    可惜用递归就可

  • 0
    @ 2009-10-11 16:30:36

    1Y

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

  • 0
    @ 2009-10-07 15:10:55

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    一次AC..........没想像中的水!注意,想练DP的同学还是做下这题。

    树形DP+多叉树转二叉树

  • 0
    @ 2009-09-24 11:25:45

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    水题不刷何以水天下?

    数据的合理组织,O(MN) ...

  • 0
    @ 2009-09-22 16:07:10

    没有想象中的水...

  • 0
    @ 2009-09-19 16:52:45

    #include

    using namespace std;

    int n,m;

    int a[301],b[301],c[301][301],d[301][301],dp[301];

    bool flog[301];

    int max(int a,int b)

    {

    return a>b?a:b;

    }

    void dfs(int num,int sum,int h,int k,int l)

    {

    for(int i=1;i>n>>m;

    for(i=1;i>a[i]>>b[i];

    memset(flog,false,sizeof(flog));

    memset(c,0,sizeof(c));

    memset(d,0,sizeof(d));

    for(i=1;i

  • 0
    @ 2009-09-18 19:59:51

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    树形dp……练手的

    program v1108;

    var f:array[0..301,0..301] of longint;

    w,r,l,nu:array[0..301] of longint;

    i,n,m,root,x,j:longint;

    function max(p,q:longint):longint;

    begin

    if p>q then exit(p) else exit(q);

    end;

    function min(p,q:longint):longint;

    begin

    if pnu[i])or(f>0)

    then exit;

    for k:=min(j-1,nu[l[i]]) downto 0 do

    begin

    t:=j-k-1;

    if t>nu[r[i]] then exit;

    dp(l[i],k);

    dp(r[i],t);

    f:=max(f,f[l[i],k]+w[i]+f[r[i],t]);

    end;

    if (nu[r[i]]>=j)and(nu[r[i]]>0)

    then begin

    dp(r[i],j);

    f:=max(f,f[r[i],j]);

    end;

    end;

    begin

    readln(n,m);

    root:=0;

    for i:=1 to n do

    begin

    readln(x,w[i]);

    if (x=0)and(root=0)

    then root:=i;

    if l[x]=0

    then l[x]:=i

    else begin

    r[i]:=r[l[x]];

    r[l[x]]:=i;

    end;

    end;

    dfs(root);

    dp(root,m);

    writeln(f[root,m]);

    end.

  • 0
    @ 2009-09-16 19:28:21

    不容易啊!!!!!

    这道题我想了3天,看了SDSC2009夏令营的lpyの绿书,结合楼下校友liujiahui的程序。

    终于在今天背过并理解了。(我昨天可是熬夜很晚还在看OI)

    今天一口气默写出来了

    但是一开始始终不对,找啊找啊……很久很久……

    原来是我一直不是很明白的多叉树转二叉树,lpyの绿书上把这么重要的东西给写错了!!!万恶的lpy……

    因为下面的程序多叉树转二叉树写的都很诡异,所以只好自己推了个代码:

    我怎么这么鄙视lpy……虽然这样非常降RP……

    万恶的 多叉树转二叉树

    for i:=1 to n do

    begin

    readln(x,a[i]);if (x=0)and(root=0)then root:=i;

    if l[x]=0 then l[x]:=i

    else begin

    r[i]:=r[l[x]];r[l[x]]:=i;

    end;

    end;

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    没有人比我的程序更简练了吧……(因为没有用记录,数组名字简单)

    const filename='p1180';

    var

    f:array[0..300,0..300]of longint;

    i,j,k,m,n,root,x:longint;

    a,l,r:array[1..300]of longint;

    function max(x,y:longint):longint;

    begin if x>y then exit(x);exit(y);end;

    procedure dp(i,j:longint);

    var k:longint;

    begin

    if (i=0)or(j=0)then exit;

    if (f0)then exit;

    dp(r[i],j);

    f:=f[r[i],j];

    for k:=1 to j do

    begin

    dp(l[i],k-1);

    dp(r[i],j-k);

    f:=max(f,f[l[i],k-1]+a[i]+f[r[i],j-k]);

    end;

    end;

    begin

    assign(input,filename+'.in');reset(input);

    assign(output,filename+'.out');rewrite(output);

    readln(n,m);root:=0;

    for i:=1 to n do

    begin

    readln(x,a[i]);if (x=0)and(root=0)then root:=i;

    if l[x]=0 then l[x]:=i

    else begin

    r[i]:=r[l[x]];r[l[x]]:=i;

    end;

    end;

    dp(root,m);

    writeln(f[root,m]);

    close(input);close(output);

    end.

  • 0
    @ 2009-09-02 09:39:54

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    树形DP 秒杀

  • 0
    @ 2009-08-31 17:55:01

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

    program p1180;

    type node=record

    l,r,d:integer;

    end;

    var f:array[0..100000]of integer;

    t:array[0..10000]of node;

    opt:array[0..1000,0..1000]of longint;

    n,m:integer;

    function max(a,b:longint):longint;

    begin

    if a>b then exit(a) else exit(b);

    end;

    procedure init;

    var i,j,x,y:integer;

    begin

    readln(n,m);

    for i:=1 to n do

    begin

    read(x,y);

    if f[x]=0 then

    t[x].l:=i

    else

    t[f[x]].r:=i;

    f[x]:=i;

    t[i].d:=y;

    end;

    end;

    function dp(i,j:integer):longint;

    var k,l,o:integer;

    begin

    if j=0 then exit(0);

    if opt0 then exit(opt);

    if (t[i].l=0)and(t[i].r=0) then

    begin

    if j=1 then opt:=t[i].d;

    end

    else if (t[i].l=0) then

    begin

    opt:=max(dp(t[i].r,j-1)+t[i].d,dp(t[i].r,j));

    end

    else if (t[i].r=0) then

    begin

    opt:=dp(t[i].l,j-1)+t[i].d;

    end

    else

    begin

    opt:=dp(t[i].r,j);

    for k:=0 to j-1 do

    opt:=max(dp(t[i].l,k)+dp(t[i].r,j-k-1)+t[i].d,opt);

    end;

    dp:=opt;

    end;

    begin

    init;

    writeln(dp(0,m+1));

    end.

  • 0
    @ 2009-09-16 14:51:04

    f表示以i为根选j节课获得学分最大值。

    f:=max(f[t[i].son,k]+f)(0

信息

ID
1180
难度
4
分类
动态规划 | 树形DP 点击显示
标签
(无)
递交数
3254
已通过
1359
通过率
42%
被复制
9
上传者