[sorting] [dichotomy] [dp]JZOJ 2747 gold picking

Description

Once upon a time, there was a maze. The shape of the maze was like a tree with roots. Each node (except for the leaf node) had exactly K sons.
At the beginning, you are at the root node. The K sons of the root node are marked as' A ',' B ',' C ' , and the K son nodes of node 'A' are marked as' AA ',' AB ',' AC ' , and so on. This tree has A total of L layers.
Now you know in advance that there is gold in M nodes, and you can send N robots to collect gold. First of all, you can specify the target nodes of each robot, so these robots will collect all the gold from the root node to the target node (including the target node), but the gold at each location can only be collected once.
Now you need to work out a goal allocation plan to get the most gold.

Title Solution

First, we rank m nodes from small to large
 So we need to make trees, in fact, we only need to connect these gold nodes together
 We found 2~m's father (or grandfather or great grandfather or great grandfather or great grandfather...) (use!! Two points!! Implementation), stored in the queue
 At last, dp
    Let's take f[i][j] as the root of the ith node, and use the j-th robot to collect the maximum number of gold
    The equation of state transition is f[x][i]=max(f[x][i],f[x][i-j]+f[y][j])
    (Ps: x is the current node, i is the currently enumerated robot, y is the next generation node, j is the next generation node)

Code

uses math;
type strx=string[55];
var     num,m,k,l,n,x,i,j:longint;
        next,last,first,bz:array[0..50050]of longint;
        a:array[0..50050]of strx;
        f:array[0..50050,0..50]of longint;
        w:string;

procedure insert(i,j:longint);
begin
        inc(num);
        next[num]:=last[i];
        last[i]:=num;
        first[num]:=j;
end;

procedure qsort(l,r:longint);
var     i,j:longint;
        mid,t:strx;
begin
        if (l>=r) then exit;
        i:=l; j:=r; mid:=a[(l+r) div 2];
        repeat
                while (a[i]<mid) do inc(i);
                while (a[j]>mid) do dec(j);
                if (i<=j) then
                begin
                        t:=a[i]; a[i]:=a[j]; a[j]:=t;
                        inc(i); dec(j);
                end;
        until i>j;
        qsort(l,j);
        qsort(i,r);
end;

function find(x:strx):longint;
var     l,r,mid:longint;
begin
        l:=1; r:=i;
        while (l<r) do
        begin
                mid:=(l+r)div 2;
                if (a[mid]<x)then l:=mid+1 else r:=mid;
        end;
        if (a[l]<>x) then exit(0) else exit(l);
end;

procedure dp(x:longint);
var     k,y,i,j:longint;
begin
        k:=last[x];
        while (k<>0) do
        begin
                y:=first[k];
                dp(y);
                for i:=n downto 1 do
                        for j:=1 to i do
                                f[x,i]:=max(f[x,i],f[y,j]+f[x,i-j]);
                k:=next[k];
        end;
        for i:=1 to n do f[x,i]:=f[x,i]+bz[x];
end;

begin
        readln(m,k,l,n);
        for i:=1 to m do readln(a[i]);
        inc(m);
        a[m]:='';
        qsort(1,m);
        x:=1;
        for i:=2 to m do
        begin
                w:=a[i];
                delete(w,length(w),1);
                j:=find(w);
                while (j=0) do
                begin
                        delete(w,length(w),1);
                        j:=find(w);
                end;
                insert(j,i);
                bz[i]:=1;
        end;
        dp(1);
        writeln(f[1,n]);
end.

Posted by Dan911 on Thu, 30 Apr 2020 05:56:57 -0700