Solution to a problem [P1064] Jinming budget plan

Topic Link

Solution [NOIP improve group 2006] Jinming budget plan

Title effect: given a series of items, each item has a price \ (V \) and weight \ (W \) , and dependencies to find a feasible embodiment article, and so as to satisfy the dependency. \ (\ sum v \ leq m \) in the case of \ (\ sum w \) as large as possible

Analysis: This question obviously tell you that it is a tree of dependencies, for example, if an item \ (v \) rely items \ (U \) , a side we do not even \ (u, v \) For convenience, we. Join a virtual point \ (0 \) , a point \ (u \) if it is even the main thing we \ ((0, u) \ )

So we end up with a tree, this tree has what characteristic?

  • An item depend on all the items are his parent
  • If an item is not selected, corresponds to the tree, all his child node can not choose

Well, the tree constructed out. Let's look at how to solve problems. First, we can use a tree dp to solve, but this is more complicated, but not run very fast. So it possible to use more familiar \ (01 \ ) backpack to solve it?

Ordinary \ (01 \) state of the backpack and the transfer equation?

\(f[i][j] = max\begin{cases} f[i - 1][j] \\ f[i - 1][j - v] + w & j \geq v\end{cases}\)

I believe we are very familiar with this, look at this problem? Tree \ (dp \) to do well, we can turn it into a linear dp . Put a tree into a sequence of how we can do? \ (The DFS \) sequence what

We later find a Fengyun tree traversal sequence , such a node son and brother left in the sequence in its front. And then what? Every step we have two decisions.

  • Choose this item, then the state \ (i \) directly by the state \ (i - 1 \) transferred from
  • Not vote for this article, it is not the son of points can not choose , then the state \ (i \) can only be transferred from its sibling from the left

Tidy, if \ (pre [u] \) that number is \ (u \) left brothers number of words:

\(f[i][j] = max\begin{cases}f[pre[i]][j]\\f[i - 1][j - v] + w & j \geq v \end{cases}\)

Analyze the time complexity? Seek postorder and \ (pre \) we can once \ (dfs \) in (O (n) \) \ find out in time

  • The total number of status: \ (nm \)
  • Transfer costs: \ (O (1) \)
    ? Then the total complexity \ (O (n + nm) \) so the overall complexity is \ (O (nm) \) and \ (01 \) backpack considerable, and this algorithms can also handle attachments have attachments (that is, the height of the tree is more than \ (2 \) ) case

Attach ugly code:

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 64;
const int maxm = maxn;
const int maxv = 33333;
struct Node{//表示物品
    int v,w;
    Node() = default;
    Node(int a,int b):v(a),w(b){}
}d[maxn],t[maxn];
struct Edge{
    int from,to;
    Edge() = default;
    Edge(int a,int b):from(a),to(b){}
}Edges[maxm];
int head[maxn],nxt[maxm],root[maxn],rp;
inline void addedge(int from,int to){
    static int tot;
    Edges[++tot] = Edge(from,to);
    nxt[tot] = head[from];
    head[from] = tot;
}
int pre[maxn],f[maxn][maxv],p = 0;
void dfs(int u){
    int tp = p;//由于后序遍历的性质,一个点的左兄弟显然是进入这个点时序列中的最后一个点
    for(int i = head[u];i;i = nxt[i]){
        Edge &e = Edges[i];
        dfs(e.to);
    }
    d[++p] = t[u];//后序遍历
    pre[p] = tp;//求左兄弟,注意,pre[t]表示序列中编号为t的节点的左兄弟的编号
}
int n,m;
int main(){
#ifdef LOCAL
    freopen("fafa.in","r",stdin);
#endif
    scanf("%d %d",&m,&n);
    for(int i = 1;i <= n;i++){//建图
        int v,w,faz;
        scanf("%d %d %d",&v,&w,&faz);
        t[i] = Node(v,v * w);//先预处理它的权值
        addedge(faz,i);//有个技巧,如果一个点是主件,我们就认为它依赖于虚拟点0
    }
    dfs(0);
    for(int i = 1;i <= n;i++)//dp求解
        for(int j = 0;j <= m;j++)
            if(j >= d[i].v)f[i][j] = max(f[pre[i]][j],f[i - 1][j - d[i].v] + d[i].w);
            else f[i][j] = f[pre[i]][j];//转移 
    printf("%d\n",f[n][m]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/colazcy/p/11514778.html