zoukankan      html  css  js  c++  java
  • P2014 选课 (树型背包模版)

    树上背包:

    树形背包就是原始的树上动归+背包,一般用来处理以一棵树中选多少点为扩展的一类题,基本做法与树上dp无异,不过在状态转移方程中会用到背包的思想。

    它基本上是这个样子的:

    存图),然后dfs进去补全子节点的信息,f数组的意思是以fa为中转点,找出fa往下的可取1~j个点时各自的最大收益。

    for(int i=1;i<=son;i++){//枚举所有儿子
      dfs(son[i]);//先处理儿子
      for(int j1=m;j1>=0;j1--){//枚举当前点用掉了多少容量(正着枚举会变成完全背包)
        for(int j2=0;j2<=j1;j2++){//枚举这个儿子分配多少
          dp[i][j1]=max(dp[i][j1],dp[i][j1-j2]+dp[son[i]][j2]);//更新状态
        }
      }
    }

    选课这题基本上就是树上背包的板子题了:

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    #include <bitset>
    #include <cmath>
    
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    const double eps = 1e-10;
    const int maxn = 310;
    const LL mod = 1e9 + 7;
    
    int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
    using namespace std;
    
    struct edge {
        int v,nxt;
    }e[maxn];
    
    int head[maxn],w[maxn],f[maxn][maxn];
    int fa[maxn];
    int cnt;
    int n,m;
    
    
    void add_edge(int u,int v) {
        e[++cnt].v = v;
        e[cnt].nxt = head[u];
        head[u] = cnt;
    }
    
    void dfs(int x) {
        for (int i = head[x];~i;i = e[i].nxt) {
            int v = e[i].v;
            dfs(v);
            for (int j = m+1;j >= 1;j--) {
                for (int k = j-1;k >= 0;k--)
                    f[x][j] = max(f[x][j],f[v][k]+f[x][j-k]);
            }
        }
    }
    
    
    int main() {
        cnt = 0;
        memset(head,-1, sizeof(head));
        cin >> n >> m;
        for (int i = 1;i <= n;i++) {
            int u,v;
            cin >> u >> v;
            fa[i] = u;
            add_edge(u,i);
            f[i][1] = v;
        }
        dfs(0);
        cout << f[0][m+1] << endl;
        return 0;
    }

    还有一种多叉树转二叉树的方法:

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    #include <bitset>
    #include <cmath>
    
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    const double eps = 1e-10;
    const int maxn = 310;
    const LL mod = 1e9 + 7;
    
    int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
    using namespace std;
    
    int f[maxn][maxn],mark[maxn];
    int l[maxn],r[maxn];
    bool s[maxn][maxn];
    int w[maxn];
    int n,m;
    
    inline void pre(int x) {    // 多叉树转二叉树
        mark[x] = 1;
        for (int i = 1;i <= n+1;i++) {
            if (!mark[i] && s[x][i]) {
                r[i] = l[x];
                l[x] = i;
                pre(i);
            }
        }
    }
    
    inline void dfs(int x) {
        if (l[x])
            dfs(l[x]);
        if (r[x])
            dfs(r[x]);
        for (int y = 0;y <= m;y++) {
            f[x][y] = f[r[x]][y];
            for (int k = 0;k <= y-1;k++)
                f[x][y] = max(f[x][y],f[l[x]][k]+f[r[x]][y-k-1]+w[x]);
        }
    
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n >> m;
        for (int i = 1;i <= n;i++) {
            int a,b;
            cin >> a >> b;
            w[i] = b;
            if (a == 0)
                a = n+1;
           s[a][i] = true;
        }
        pre(n+1);
        dfs(n+1);
        cout << max(f[l[n+1]][m],f[r[n+1]][m]) << endl;
        return 0;
    }
  • 相关阅读:
    Tomcat6 只允许指定域名访问,禁用IP地址访问,防止恶意解析
    java实现http协议发送和接收数据
    firefox下jquery ajax 返回 [object XMLDocument]处理
    js 格式化时间
    Jquery中的offset()和position()深入剖析(元素定位)
    sql格式化时间
    tomcat绑定域名
    查看tomcat的版本号
    [转载] IOS 获取网络图片的大小 改变 图片色值 灰度什么的方法集合
    CABasicAnimation动画
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12337944.html
Copyright © 2011-2022 走看看