zoukankan      html  css  js  c++  java
  • DP整理(未完待续)

    一、资源问题

    T1 机器分配

    已知条件:每家公司分配x台机器的盈利

    令f[i][j]表示前i公司分配j台机器的最优解

    转移:f[i][j]=max(f[i-1][j-k]+w[i][k])

    初始化:f[1][i]=w[1][i]

    枚举第i个公司分配k台(直接利用已知条件),那前i-1个公司分配j-k台

    T5 化工厂装箱员

    一段包含A、B、C的排列,区间从左往右扫,每次区间包含10个元素,每次将区间内所有的A或B或C删除,区间再往右扩张至10个元素,问最小删除次数

    令f[d][a][b][c]表示区间总共覆盖了d个数,这一次区间内有a个A,b个B,c个C的最优解

    初始化:f最大值

    状态转移:f[d][a][b][c]=min(f[d][0][b][c],f[d][a][0][c],f[d][a][b][0])+1

    有了第一维d,防止了f状态的重复

    二、上升子序列问题

    T1 朴素的最长上升子序列

    n2:f[i]=j 以第i个数结尾的最长上升子序列长度为j

    nlogn:f[i]=j 长度为i的最长上升子序列中,第i个数最小是j

    T2 包含第k个数的最长上升子序列

    设第k个数为m

    删去k前面>=m的,k后面<=m的,同上

    k前>=m的删去后,k前面的最长上升子序列的最大值一定比m小,加上m后一定比原来更优

    k后<=m的删去后,防止了答案绕过第k个数

    T3 最长上升子序列划分

    将上升子序列分成2部分==>最长不上升子序列长度<=2

    三、线型DP

    T1、舞蹈家怀特先生

    f[i][l][r]跳了i步,第i步左脚在l,右脚在r的最优解

    预处理:move[i][j] 从i移向j所需的代价

    状态转移:f[i][l][r]=min(min(f[i][x][r]+move[x][l]),min(f[i][l][x]+move[x][r]))

    特殊处理:第一步到两脚都迈出第一步

    T2、绿色通道

    n道题,解决每个题需要一定时间,每个题可以解决,也可以空过去,给出时间总限制,最小化最大空题段

    令f[i]表示抄第i道题所花费的最小时间

    状态转移方程:f[i]=min(f[j])+time[i] max(0,i-mid-1)<=j<=i-1

    初始化:f数组极大值,f[0]=0

    注:本体朴素的DP会TLE,所以要用线段树或单调队列优化

    T3、积木游戏

    n个积木堆m堆,满足堆与堆之间各积木序号升序,每堆内部从下往上积木序号升序

     f[k][i][j][l] 表示 前i个积木分为k组,第k组最后一个是j,j的摆放方式为l的最大高度

    状态转移:

    ① 与前面积木合为一组  f[k][i][i][l]=max(f[k][i][j][t])+high[i]  

    ② 自己另放一组  f[k][i][i][l]=max(f[k-1][i-1][j][t])+high[i] 

    ③ 不放 f[k][i][j][l]=f[k][i-1][j][l] 

    其中0<=j<i    0<=t<=2 

    状态压缩:

    0 表示  ab面为底;1 表示 ac面为底; 2表示bc面为底

    ans=max(f[m][n][i][j]) 1<=i<=n,0<=j<=2

    编程复杂度优化:

    先对输入每块积木的a,b,c排序,这样在DP中就不用判断同一块积木的长宽高

    T4 、括号序列(加括号使之成为规则序列)

    f[i][j] 序列i——j 成为规则序列最少添加多少

    状态转移:if(i与j能匹配) f[i][j]=f[i+1][j-1]

                 f[i][j]=min(f[i][k]+f[k+1][j]) i<=k<j

    初始化:f[i][i]=1

              f[i][j]=0 (i>j) 

             其余极大值

    四、划分型DP

    T1 乘积最大

    f[i][j]表示前i个数添加了j个乘号的最优解

    预处理:w[i][j] 第i-j的数

    状态转移:f[i][j]=max(f[k][j-1]*w[k+1][i])

    T2 数的划分

    将n划分为几个可重复正整数之和的方案数,顺序不同视为同种方案

    f[i][j] 把i划分为j个正整数的方案数

    状态转移:f[i][j]=f[i-1][j-1]+f[i-j][j]

    初始化:f[0][0]=1

    T3 统计单词个数

    f[i][j] 前i个字母划分为j段的最优解(最多单词个数)

    预处理:w[i][j] 第i到j个字母的单词数

    状态转移:f[i][j]=max(f[k][j-1]+w[k+1][i])

    初始化:f[i][1]=w[1][i]

    T4 数字游戏

    f[i][j][k] 第i—j个数划分为k个部分的最优解(各部分和的乘积)

    预处理:w[i][j] 第i—j个数的和

    状态转移:f[i][j][k]=max(f[i][l][k-1]*w[l+1][j])

    预处理:f[i][j][1]=w[i][i]

    五、棋盘DP

    T1 棋盘分割

    dp[k][x1][x2][y1][y2] 矩形左上角标号为(x1,y2) ,右上角标号为(x2,y2),分为k个矩形 所得到的最小平方和
    初始化:dp 极大值
    预处理:s[x1][x2][y1][y2]   矩形左上角标号为(x1,y2) ,右上角标号为(x2,y2)内所有数和的平方
              dp[1][x1][x2][y1][y2]=s[x1][x2][y1][y2] (相当于一刀也不切的情况)
    状态转移:dp[k][x1][y1][x2][y2]=min(
                 dp[k-1][x1][y1][x][y2]+s[x+1][y1][x2][y2]) //横着切,取上面一部分继续切
                 dp[k-1][x+1][y1][x2][y2]+s[x1][y1][x][y2]//横着切,取下面一部分继续切
                 dp[k-1][x1][y1][x2][y]+s[x1][y+1][x2][y2]//竖着切,取左边一部分继续切 
                 dp[k-1][x1][y+1][x2][y2]+s[x1][y1][x2][y] //竖着切,取右边一部分继续切
    )
    转移过程可用记忆化搜索实现
  • 相关阅读:
    [BZOJ 1019][SHOI2008]汉诺塔(递推)
    [BZOJ 1018][SHOI2008]堵塞的交通traffic(线段树)
    [BZOJ 1017][JSOI2008]魔兽地图DotR(树形Dp)
    [BZOJ 1015][JSOI2008]星球大战starwar(并查集+离线)
    [BZOJ 1014][JSOI2008]火星人prefix(Splay+二分+hash)
    Vue脚手架创建项目目录详解
    Vue-cli3 vue.config.js配置详解
    Systemd指令大全
    CentOS7 常用命令集合
    Centos7虚拟机集群配置
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6426147.html
Copyright © 2011-2022 走看看