初涉分组背包 HDU 1561 The more,The better

给出一个森林,每棵树均为一组物品,首先推出每棵树可以组成的物品种类。

然后是基本的分组背包模板。

即 最外层枚举组数,次外层枚举背包容量,内层枚举物品体积。

对于每棵树有 ans[root][i+j] = ans[root][ i ] + ans[son][ j ]。

题水数据也水,不多说了。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long int
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007
#define LM(a,b) (((ULL)(a))<<(b))
#define RM(a,b) (((ULL)(a))>>(b))

using namespace std;

const int MAXN = 210;

struct N
{
    int u,v,w,next;
} edge[MAXN*2];

int head[MAXN];

int Top;

void Link(int u,int v,int w = -1)
{
    edge[Top].u = u;
    edge[Top].v = v;
    edge[Top].w = w;
    edge[Top].next = head[u];
    head[u] = Top++;
}

void Init_head_Top(int n)
{
    memset(head,-1,sizeof(int)*(n+2));
    Top = 0;
}

int dp[MAXN];

int ans[MAXN][MAXN];

int root[MAXN];

int Top_Root;

int price[MAXN];

void dfs(int s,int m)
{
    ans[s][1] = price[s];

    for(int p = head[s] ; p != -1; p = edge[p].next)
    {
        dfs(edge[p].v,m);

        for(int i = m;i >= 0; --i)
        {
            for(int j = m-i;j >= 1; --j)
            {
                if(ans[s][i] != -1 && ans[s][i+j] < ans[s][i] + ans[edge[p].v][j])
                    ans[s][i+j] = ans[s][i] + ans[edge[p].v][j];
            }
        }

    }
}

int main()
{
    int n,m;

    int i,j,k,v;

    while(scanf("%d %d",&n,&m) && (n||m))
    {
        Init_head_Top(n);

        Top_Root = 0;

        memset(dp,-1,sizeof(dp));
        memset(ans,-1,sizeof(ans));

        for(i = 1; i <= n; ++i)
        {
            scanf("%d %d",&v,&price[i]);
            if(v)
                Link(v,i);
            else
                root[Top_Root++] = i;
        }

        for(i = 0; i < Top_Root; ++i)
        {
            dfs(root[i],m);
        }

        dp[0] = 0;

        for(j = 0; j < Top_Root; ++j)
        {
            for(i = m;i >= 0; --i)
            {
                if(dp[i] != -1)
                {
                    for(k = m-i;k >= 1; --k)
                    {
                        if(ans[root[j]][k] != -1 && dp[i] != -1 && dp[i+k] < dp[i] + ans[root[j]][k])
                            dp[i+k] = dp[i] + ans[root[j]][k];
                    }
                }
            }
        }

//        for(i = 1; i <= m; ++i)
//        {
//           // printf("cost = %2d w = %2d\n",i,dp[i]);
//        }
//
//        for(i = 1; i <= n; ++i)
//        {
//            for(j = 1; j <= m; ++j)
//            {
//                //printf("%2d ",ans[i][j]);
//
//            }
//           // puts("");
//        }

        int Max = dp[1];

        for(i = 1; i <= m ; ++i)
            Max = max(Max,dp[i]);
        printf("%d\n",Max);
    }

    return 0;
}

初涉分组背包 HDU 1561 The more,The better,码迷,mamicode.com

时间: 2024-10-10 02:09:16

初涉分组背包 HDU 1561 The more,The better的相关文章

hdu 1561 树形dp+分组背包

题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值. 一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值. 状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)                    dp[v][j] = m

HDU 3033 分组背包

http://www.hgy413.com/1319.html 简介DeviceIoControl的三种通信方式 HDU 3033 分组背包,布布扣,bubuko.com

HDU 3033 I love sneakers! 分组背包

我是个逗比...真心不是搞算法的料 不太中规中矩的分组背包,分组至少选一件商品.dp[i][j] 可以由当前dp[i-1][j-c] 和 dp[ i ][j-c]更新得到. #include <iostream> #include <algorithm> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <cmath

HDU 6125 Free from square(状态压缩+分组背包)

http://acm.hdu.edu.cn/showproblem.php?pid=6125 题意: 在${1,2,3,...n}$的数中选择1~k个数,使得它们的乘积不能被平方数整除(1除外),计算有多少种取法. 思路: 考虑一下他们的质因子,如果两个数有相同的质因子,那么它们两个肯定是不能同时选的.这是不是很像分组背包,但是如果以质因子来分类的话,一个数就可能处于多个背包当中,这样就不行了,因为一个数你只能在一个背包中. 这题的数据范围很小,在500的范围内,质数的平方数小于500的就8个数

hdu 1712 ACboy needs your help(分组背包入门)

1 /********************************************************** 2 题目: ACboy needs your help 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=1712 4 题意: 一开始输入n和m,n代表有n门课,m代表你有m天,然 5 后给你一个数组,val[i][j],代表第i门课,在通过j 6 天去修,会得到的分数.求在m天能得到的最大分数. 7 算法: 分组背包 8 9

hdu 3033 I love sneakers!(分组背包,每组至少取一件)

http://acm.hdu.edu.cn/showproblem.php?pid=3033 大致题意:某人要买鞋子,有k种鞋,要求每种鞋至少买一双,给出每双鞋子的花费和价值,问m元钱可以买到的鞋子的最大价值是多少. 思路:分组背包问题.与传统的分组背包不同:每组物品至少取一件:且每组中物品任意取. 想一想传统的分组背包,每组至多选一件: for 所有的组k     for v=V..0         for 所有的i属于组k             f[v]=max{f[v],f[v-c[i

HDU 3033 I love sneakers! (01背包+反分组背包)

题意:给你 n,m,k,表示有k种鞋子共n双,你有m的容量: 每双鞋子有容量p和价值v:问是否买全k种鞋子,若能在容量为m的情况下最多能买到鞋子的价值为多少: 每双鞋子只能买一次(01背包),每种鞋子至少买一种(分组背包:每组只能有一个)与传统分组背包的限制相反. 注意初始化!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map&g

HDU 4003 Find Metal Minaral 树上瞎搞分组背包

对于分组背包,每组选且只选一件商品的写法只想出了二维数组的写法. dp[s][k] 表示 在前s类中选取价格为 k 的商品的最优解. dp[s][k] = max( dp[s-1][k-product[s][j].c] + product[s][j].w).dp[s][k]每次只会有dp[s-1]更新得到,保证了前s-1类商品的选取. 对于此题,可以把每棵子树的情况看成一类商品,递归求解. dp[s][k]表示在s子树上投入k个机器人时的最优解. 当k == 0时,表示在s点投入1个机器人,且此

HDU 4341 Gold miner(分组背包)

http://acm.hdu.edu.cn/showproblem.php?pid=4341 题意: 一个人在原点(0,0)抓金子,每块金子是二维坐标平面的一个点(x,y)且y>0. 每块金子有一个价值v和获得需要的时间t.如果多个金子在一条从原点射出的直线上,那只能先抓近的,再抓远的.求在给定时间T下,所能获得的最大价值. 分析: 首先想想如果所有点都不共线是什么情况? 就是在给定时间T内要获取最大的价值和的点, 且所有点都可以任意选取. 那么这就是一个01背包问题. 不过如果存在共线的点,那