首页 > 其他分享 >[刷题笔记] Luogu P1064 [NOIP2006 提高组] 金明的预算方案

[刷题笔记] Luogu P1064 [NOIP2006 提高组] 金明的预算方案

时间:2023-08-23 20:45:23浏览次数:53  
标签:NOIP2006 背包 int Luogu include vv noww P1064 dp

Problem

Analysis

我们发现如果忽略主从关系,那这道题就是一个裸的 01 背包问题。

主从关系处理也非常简单,借鉴 P2014 选课 的经验,转换成树上背包问题。

同理,本题是一个森林,若将 0 号节点参与建树的话就可以把森林转换成树,处理方便。

具体地,设 \(f_{i,j}\) 表示以 \(i\) 为父节点,剩余价钱(这里看作重量)为 \(j\) 时的最大价值。显然我们需要预处理出价值 = 重要度 \(\times\) 价钱。

树上背包具体实现的时候需要先处理子节点。

Code

/*

有依赖关系的dp统一用树上背包处理。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 40000;
int n,m;
int f[200][N];
int w[N],v[N];
vector <int> Edge[N];
void dp(int noww,int t,int fa) //树上背包类似于记搜
{
    if(t <= 0) return; //这个参数是必须的!和选课不同
    for(int i=0;i<Edge[noww].size();i++)
    {
        int vv = Edge[noww][i]; 
        if(vv == fa) continue; //不能回去
        for(int j=n-w[vv];j>=0;j--) f[vv][j] = f[noww][j] + v[vv]; //只有先取now才能取用vv,先后顺序需要注意。题目保证一个儿子只对应一个父亲。显然枚举重量j的下限是总重量-这个儿子的重量。不能再小于它!显然。
        dp(vv,t-w[vv],noww); // 先搜儿子,树上dp板子
        for(int j = n;j >= w[vv];j--) // 01背包倒着搜
        {
            f[noww][j] = max(f[noww][j],f[vv][j-w[vv]]); //我们已经预处理完了,直接取即可 
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++) 
    {
        int v1,p,q;
        cin>>v1>>p>>q;
        Edge[q].push_back(i); //双向建边
        Edge[i].push_back(q);
        v[i] = v1*p; //预处理每件物品的价值
        w[i] = v1;
    }
    m++; 
    dp(0,n,0);  //虚拟节点参与,变森林为树qwq(和选课类似)
    int maxn = 0;
    for(int i=0;i<=n;i++)
    {
        maxn = max(maxn,f[0][i]); //f 数组第一维存的是剩余重量,所以需要是0.至于第二维我们显然不知道以哪个节点为fa的时候价值最大,取max即可。
    }
    cout<<maxn<<endl;
    return 0;
}

标签:NOIP2006,背包,int,Luogu,include,vv,noww,P1064,dp
From: https://www.cnblogs.com/SXqwq/p/17652737.html

相关文章

  • [刷题笔记] Luogu P2679 [NOIP2015 提高组] 子串
    ProblemDescription我们可以换个思路。从字符串\(A\)中拿出\(k\)个字串使其变成\(B\)。求有几种不同的方案?Analysis我们发现\(A\)中的一个字符取或者不取影响后面的决策,这并不代表它一定有后效性,我们可以记录这一层状态。和最长公共子序列同理,定义\(f_{i,j,k,l}(\fo......
  • [刷题笔记] [【LGR-155-Div.3】T4] Luogu P9572 「NnOI R2-T4」Colorful Days♪
    ProblemDescription有两个数组\(A,B\),我们可以将\(A\)数组无限次重复拼接。求最少需要多少次拼接使得拼接后的\(A,B\)的最长公共子序列最大。Analysis我们要学会从题目中找到一些信息,比如说本题的数据范围:对于\(100\%\)的数据,保证\(1\leqn,m,S_i,T_i\le10^6\),\(......
  • Luogu P1119 灾后重建
    在洛谷中查看解法1(我想的解法,不完全正确):很常见的套路:将询问按时间排序。时间复杂度:\(O(\;q\,(n\,logn+m)\;)\),即\(10^9\),开\(O2\)才能过。非常麻烦有没有,但我对拍的时候发现了一组数据很奇怪,待会给你们看看,我看看能不能hack#include<bits/stdc++.h>usingnamespacestd......
  • 【LuoGu 1363】幻象迷宫——深度优先搜索 + 读题
    幻象迷宫题目背景(喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫。)WD:呜呜,肿么办啊……LHX:momo...我们一定能走出去的!WD:嗯,+U+U!题目描述幻象迷宫可以认为是无限大的,不过它由若干个\(N\timesM\)的矩阵重复组成。矩阵中有的地......
  • Luogu P3369 【模板】普通平衡树 01Tire树解法
    题目传送门闲话:Luogu总共105篇题解中只有4篇01Tire树解法,虽说是非正解但未免也太少了些(貌似也不少?)……总之01Tire树的效率并不低,这道题用01Tire是很轻松的。Q:这题为什么可以用01Tire树解?能否解决一个问题,无非于三个点:可行性,空间,时间。本题要求维护一个有序数集,能进行元素修改......
  • 牛的旅行 luoguP1522 多余的换行造成的影响
    牛的旅行#include<bits/stdc++.h>usingnamespacestd;intread(){intf=1,x=0;charc=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){......
  • Luogu P9510 『STA - R3』高维立方体 题解
    题目传送门没见过这玩意,写个题解记下。题目大意周知斐波那契数列定义为:\[\operatorname{fib}(n)=\left\{\begin{aligned}1&&n\le2\\\operatorname{fib}(n-1)+\operatorname{fib}(n-2)&&n>2\end{aligned}\right.\]然后定义(\(n\le0\)函数值为\(0\))\[f(n)......
  • [Luogu P8716] 回文日期 题解
    STEP1:分析题目大意:给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。这一题一眼看出是P2010的升级版,所以要先考虑到超时问题,因为如果一天一天地枚举,时间复杂度会非常高,所以我们不能直接枚举。因为题目只要"回文",所以我们只......
  • LuoguP1717 钓鱼
    题面题目分析动态规划。\(\bullet\)设计状态。思考:我从哪里来?从上一个湖过来。我到哪里去?到下一个湖去\(or\)继续在这个湖钓鱼。设\(dp[pos][tim]\)为前\(pos\)个湖花费了\(tim\)分钟所能钓的最大的鱼数量。\(\bullet\)转移状态。(为了方便计算,我们将题目中的数据......
  • [刷题笔记] Luogu P1725 琪露诺
    ProblemDescription若当前在\(pos\)位置,每次可以在\([pos+l,pos+r]\)区间内任选一个点跳。每跳到一个地方就可以获得这个地方的值,最后跳到位置\(pos\geqn\)即为结束,求如何跳才能使结束的时候获得的值最大?Analysis我们发现所有操作都是在一条链上完成的,显然若再次跳到这个位......