• 【笔记】还是发上来作为学习过的记录吧,凌乱,勿进


    背包

    有限背包(多重背包)

    拆分方法:倍增拆分
    (倍增拆分!=二进制拆分)
    

    拿走01背包

    前后做两次DP,相当于前后缀
    F[I][J]表示前i个物品,取体积为j的最大价值
    G[i][j]表示第i+1到第n个物品,取体积为j的最大价值
    拿掉第p个物品时,枚举a(0~m),拿走第p个物品后,最大价值就是f[p-1][a]+g[p+1][m-a]的最大值。
    DP题很少删东西,都是加东西,所以把删转化为加
    

    题目:https://darkbzoj.tk/problem/3163

    边表

    Struct edge{
    	int e, next;
    }ed[maxn];
    
    Int first[maxn];
    
    Void ins(int s, int e)
    {
    	En++;
    	Ed[en].next = first[s];
    	First[s]=en;
    	Ed[en].e=e;
    }
    

    树形DP

    状态设计
    F[i]表示以i为根的子树(必有这一维)
    初始化
    对叶节点做初始化
    转移
    把儿子合起来转移给父亲

    最大独立集
    没有上司的舞会 战略游戏

    聚合
    需要另外一个DP来聚合

    依赖背包问题(树形背包)
    基于连通性的状态压缩的动态规划——Cdq

    题目

    背包*3
    独立集
    树的直径
    依赖背包问题
    4516

    送分
    特殊类型DP
    矩阵快速幂DP
    思维难度DP

    数位DP

    一般框架:l~r之间满足条件的数的个数
    统一状态设计
    已知l,r,求l,r之间有几个数
    转化为:
    已知x求0<=y<=x中y的个数
    状态
    x=xk x(k-1) x(k-2)....x3 x2 x1
    x有k位
    y=yk.......
    (y的位数未知)
    F[i][j]表示方案数(个数)
    i表示从高到低填到第i位, j=0/1表示当前我已经填的这些位是小于x还是等于x
    一位一位转移
    初始化
    F[k+1][1]=1
    转移
    直接枚举第i-1位填啥
    For(j = 0 to x_(i-1)) //对于f[i][1],y和x的前i位都相等,为了保证y<=x,y的第i-1位必须小于等于x的i-1位
    F[i-1][x_(i-1)==1] += f[i][1]
    答案
    F[1][0]+f[1][1]

    1.前缀和转化
    2.状态设计有的i(位数),j(0/1)
    (除非很特殊,告诉y有k位数(那就第1位填0,后面随便填。或第一位填1,)??
    3.初始化
    4.转移

    练习

    小凯的数字

    代码

    int solve(int x)
    {
    Memset(f,0,sizeof(f));
    Int k=0;
    While(x)
    {
    	Y[++k] = x%10;
    	X = x/10;
    }
    F[k+1][1]=1;
    For(int i=k+1;i>=2;i--)  //已将填好i, 要填i-1
    For(int j=0;j<=1;j++)
    For(int r=0;r <=9;r++)
    {
    if(j == 1 && r >y[i-1]		continue;
    F[i-1][j &&(r==y[i-1])] += f[i][j];    //当j是1时,表示前i位都是相等的;当r=y[i-1]时,第i-1位也是相等的
    }
    	Return f[1][0] +f[1][1];
    }
    Int l, r;
    Ans=solve(r) – solve(l)
    

    数位之和

    F[i][j]表示个数
    G[i][j]表示数位之和
    r表示第i-1位填的数
    对于第i-1位,g[i-1][j] += g[i][j] + k*f[i][j]
    

    代码

    int solve(int x)
    {
    Memset(f,0,sizeof(f));
    Int k=0;
    While(x)
    {
    	Y[++k] = x%10;
    	X = x/10;
    }
    F[k+1][1]=1;
    For(int i=k+1;i>=2;i--)  //已将填好i, 要填i-1
    For(int j=0;j<=1;j++)
    For(int r=0;r <=9;r++)
    {
    if(j == 1 && r >y[i-1]		continue;
    g[i-1][j &&(r==y[i-1])] += g[i][j] + r*f[i][j];    //当j是1时,表示前i位都是相等的;当r=y[i-1]时,第i-1位也是相等的
    }
    	Return f[1][0] +f[1][1];
    }
    Int l, r;
    Ans=solve(r) – solve(l)
    

    数位差大于2————多加一维

    F[i][j][k]  k表示第i位填的啥
    

    练习
    SCOI2009 BZOJ2006 P2657 windy

    数位回文

    DP一半
    注意前面回文到后面要满足不大于x(唯一造成这个不合法问题)
    状态
    F[i][j][k] j=0/1,表示前i位的大小关系 k=0/1/2 表示后i位的大小关系

    练习
    SCOI2012 镜像数

    数位乘积为k

    如果某位填了0,k=0
    DP1 k!=0
    这个k含的质因子只有2,3,5,7,不然大于9没法用一位表示
    质因数分解,如果有两位以上质因数,无解
    F[i][j][a][b][c][d] [a][b][c][d]表示k,k=2^a +3^b + 5 ^c +7 ^ d

    DP2 k==0
    ??????????

    没法前缀和的时候

    取MAX

    状态
    F[i][j][k][p]
    I第几位,j=0/1 表示x 小于 r 或 x 等于 r, k = 0/1 表示x 大于l 或 x = l
    P表示第i位填的是啥

  • 相关阅读:
    Tree 点分治
    [LUOGU4149][IOI2011]Race
    [BZOJ2152] 聪聪可可
    [LUOGU3413] SAC#1
    [JZOJ5776]【NOIP2008模拟】小x游世界树
    [JZOJ5775]【NOIP2008模拟】农夫约的假期
    [JZOJ5781]【NOIP提高A组模拟2018.8.8】秘密通道
    [JZOJ5778]【NOIP提高A组模拟2018.8.8】没有硝烟的战争
    [JZOJ5773]【NOIP2008模拟】简单数学题
    [JZOJ5459]【NOIP2017提高A组冲刺11.7】密室
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/14453761.html
Copyright © 2020-2023  润新知