zoukankan      html  css  js  c++  java
  • #QBXT2020寒假 Day 5

    Day 5

    几类背包问题

    疯狂讲解

    1.01背包

    f[i][j]=max(f[i-1][j],f[i-1][j-t_i]+v_i)
    

    4.二维DP

    f[i][j][k]表示前i株中采集,用j个单位时间, 消耗k点体力值,最大价值。
    f[i][j][k]
    =max(f[i-1][j][k],f[i-1][j-t_i][k-e_i]+v_i)
    

    5.分类DP

    n株草药,每株有价值、采集时间、草药类别。 最多采集m个单位时间。相同类别的草药只能采一株, 求最大价值。

    n≤100,m≤1000

    f[i][j]表示前i类中采集,用j个单位时间,最大价值。
    f[i][j]=max(f[i-1][j],f[i-1][j-t_u]+v_u)
    u是i类的。
    

    6.输出方案:链表储存

    n株草药,每株有一个价值和采集时间。最多采 集m个单位时间。求最大价值,输出任意一种方案。

    n≤100,m≤1000

    f[i][j]表示前i株中采集,用j个单位时间,最 大价值。
    f[i][j]=max(f[i-1][j],f[i-1][j-t_i]+v_i)
    g[i][j] 表示g[i][j] 是从f[i-1][j] 还是f[i-  1][j-t_i]+v_i转移过来。
    从g[n][m]倒推回去,求出方案。
    

    搭建双塔

    VIJOS

    给出n个积木,每个积木有一个高度。

    选出一些积木,将它们分成两组,每组的高度 和相等。

    求最大高度和。

    n≤100,积木高度和≤2000

    CYC的思路是这样的

    f[k][i]表示第i个积木放在第k个塔上
    

    很显然不对 fuck

    正解:

    f[i][j]表示从前i个积木中选,两组高度差为j, 高度较小的那一组高度最大是多少。
    f[i][j]=max(f[i-1][j],  f[i-1][j+a_i]+a_i,f[i-1][|j-a_i|]+max(0,a_i-j))
    f[n][0]即为答案。
    

    老师:看上去会超时

    多♂人背包??

    VIJOS luogu

    求01背包的前k优解

    相当于是求选出体积恰为V的方案中,价值前k 大的方案的价值和。

    f[i][j][k]表示从前i个物品中选择,体积是j 的方案中价值第k大是几。

    f[i][j][]从f[i-1][j][]和f[i-1][j-a_i][]转移。

    每次更新的时候,枚举所有max(f[i-1] [j],f[i-1] [j-ai])排序,取前k个

    那么会不会重复?

    只需要把数组初始化为很大的值,然后f[0][0][1] = 0就可以了。

    金明的预算方案

    luogu

    有依赖关系的背包。
    转移时,主件、附件作为一个整体来转移。分 多种情况:不买、只买主件、买一个主件和附件1、 买一个主件和附件2、买主件和两个附件。
    f[i][j]=f[i-1][j],f[i-1][j-aw]+av  f[i-1][j-aw-bw]+av+bv
    f[i-1][j-aw-cw]+av+cv
    f[i-1][j-aw-bw-cw]+av+bv+cv
    

    飞翔的小鸟

    VIJOS luogu

    最长上升子序列

    if(i > j && a[i] > a[j]) f[i] = max(f[j]) + 1;
    

    最长公共子序列

    f[i][j]表示从A中前i个数、B中前j个数中选择, 最长公共子序列长度。

    f[i] [j]

    =max(

    f[i-1] [j],

    f[i] [j-1],

    f[i-1] [j-1] + 1 (if(ai == bi))

    其他类型讲解

    区间DP

    环形DP

    树形DP

    数位DP

    状态压缩DP

    区间DP

    合并果子

    在一个果园里,多多已经将所有的果子打了下 来,而且按果子的不同种类分成了不同的n堆,排成 一排。多多决定把所有的果子合成一堆。

    每一次合并,多多可以把相邻两堆果子合并到 一起,消耗的体力等于两堆果子的重量之和。可以 看出,所有的果子经过n-1次合并之后,就只剩下一 堆了。多多在合并果子时总共消耗的体力等于每次 合并所耗体力之和。

    求最小体力消耗。 n≤100

    贪心不就行了

    f[i] [j]表示将i~j堆果子合成一堆需要的最小 体力值。

    枚举最后一次合并的情况。 f[i] [j]=min(f[i] [k]+f[k+1] [j])+val[i] [j]

    最后的答案就是f[1] [n]

    一般形式:

    以区间为端点设置f数组

    矩阵取数游戏

    每行都是独立的,所以每行单独来做就行。

    考虑一行。

    f[i] [j]表示i~j作为单独的一部分,按照规定 取,最大得分。

    枚举取最左还是最右。 f[i] [j]=max( 2*(f[i+1] [j]+a[i])

    2*(f[i] [j-1]+a[j]) )

    高精度。

    能量项链

    复制一遍加在后面,就变成链上的了。

    f[i] [j]表示将i~j聚合,最大是多少。 枚举最后一次聚合情况。 f[i] [j]=max(f[i] [k]+f[k+1] [j]+...)

    能量项链

    项链

    项链

    实际上是一个树结构。

    f[i] [j]表示在i为根的子树中选j节课,最大学

    分。

    从子结点转移到根结点时,实际上相当于一个 序列上的DP。

    每次访问一个点的时候访问他的所有子节点(Si),然后要访问M个节点,分组背包的复杂度是(m^2),所以复杂度为

    [m^2 imes sum_{i = 1}^{m} s_i ]

    加分二叉树

    f[i] [j]表示i~j表示一棵树的中序遍历时,这棵树最大加分。

    枚举根结点位置。

    f[i] [j]=f[i] [k-1]*f[k+1] [j]+v[k]

    i≤k≤j

    至于先序遍历,实际上就是求方案。每个区间 都记录分界点,递归下去生成先序遍历。

    互不侵犯

    在N×N的棋盘里面放K个国王,使他们互不攻击, 共有多少种摆放方案。

    国王能攻击到它上下左右,以及左上左下右上 右下八个方向上附近的各一个格子,共8个格子。

    1 <=N <=9

    ** 异或:相同为0,不同为1 **

    借机讲一下对拍

    老师AC了就不讲了

    好了老师开始讲对拍了

    以a + b 为例子

    首先我们写一个(自以为正确的)

    然后我们写一个暴力解法

    正解
    #include <iostream>
    using namespace std;
    int a,b;
    int main(){
        cin >> a >> b;
        cout  << a + b;
    }//lcez_cyc
    

    再写暴力解

    #include <iostream>
    using namespace std;
    int a,b,ans;
    int main(){
        cin >> a >> b;
        while(a--) ans++;
        while(b--) ans++;
        cout << ans << endl;
        return 0;
    }
    

    然后写数据生成器

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int main(){
        
    }
    
  • 相关阅读:
    数据库事务的4种隔离级别
    线程竞争与同步
    flex 1与flex auto
    React环境搭建
    vue与mapbox
    前端-URL到页面显示的全过程
    监听滚动事件
    点击上下箭头,页码发生改变
    鼠标滑过元素,div显示,并根据scrollTop向下移动
    KB/MB/GB。。单位换算
  • 原文地址:https://www.cnblogs.com/Cao-Yucong/p/12220579.html
Copyright © 2011-2022 走看看