tk's blog
  • tk's blog Read Me
  • 算法相关
    • 数据结构
      • 【集训整理】 旋转treap模板
      • 二叉树及相关数据结构的java语言实现
      • 快乐树0x01:AVL树的java实现
      • 快乐树0x02 线段树实现(c++)
      • 链表的Java语言实现
    • 算法
      • DP的背包问题小结-java语言描述
      • 【集训整理】2-SAT问题 模板题
      • 【集训整理】Tarjan算法 模板题
      • 【集训整理】差分约束 模板题
      • 【集训整理】最近公共祖先LCA 模板题
      • 二分查找与二分答案-java实现
      • 动态规划-java语言练习一:暴力DP
      • 快速幂
      • 状态压缩DP-java描述
      • 差分
      • 乘法逆元
    • 题解
      • CFRound-GoodBye2022题解
  • java相关
    • Java与算法竞赛——注意事项摘录
    • java面向对象简要总结 一
    • java面向对象简要总结 三
    • java面向对象简要总结 二
  • 后端相关
    • Linux-Crontab命令
    • Spring Data JPA 使用方法
    • Spring集成Artemis实现JSM的异步消息传递
    • Spring使用自定义配置项
    • MIT6.824分布式系统Lab1.MapReduce笔记
    • MIT6.824分布式系统Lab2-Raft-A笔记
    • MIT6.824分布式系统Lab2-Raft-B笔记
  • 杂谈
    • 杂谈-关于2021
  • 杂项
    • c语言 scanf的返回值
    • 系统设计
  • 计科基础
    • 编译原理
      • 编译原理:词法分析笔记
    • CSAPP 第二章笔记
    • 计算机组成原理笔记
    • CSAPP Lab1. Datalab
    • CSAPP Lab2 Bomblab
  • C++每日一题
    • C++每日一题 Day 1 肥宅水
    • C++每日一题 Day 2 数字反转
    • C++每日一题 Day 3 理五的凡尔赛风气
    • C++每日一题 Day 4 我喜欢这个数
    • C++每日一题 Day 5 数字楼梯
    • C++每日一题 Day 6 插火把
    • C++每日一题 Day 7 贪吃蛇
    • C++每日一题 Day 8 蒙德最强战力
    • C++每日一题 Day 9 璃月七星选举
    • C每日一题 Day 2 肥宅水
    • C每日一题 Day 3 理五的凡尔赛风气
    • C语言每日一题 Day 1 荧妹好感队
由 GitBook 提供支持
在本页
  • T1. 乌龟棋 线性DP
  • 分状态
  • 转移方程
  • 代码
  • T2. 樱花 多重背包
  1. 算法相关
  2. 算法

动态规划-java语言练习一:暴力DP

上一页二分查找与二分答案-java实现下一页快速幂

最后更新于2年前


重新进行算法的一个卷,主要复习高二学的动态规划知识(

练习题目参考洛谷提单:

练习暴力DP主要是先找回DP的感觉,练习推转移方程。

T1. 乌龟棋 线性DP

[P1541

题目讲从起点到终点,每个点有不同的分数,有指定数量的1,2,3,4号牌,每张最多用一次,用几号牌乌龟就走几格。求能获得的最高分数。

设num[i]为i处的分数,count[i]为某号牌的张数。

分状态

可以看出状态可以由使用不同种牌的次数来划分,因此设s[a][b][c][d]为使用了a张1号,b张2号...牌能取得的最高分数。

显然,s[0][0][0][0]=num[1],我们要求的就是s[num_a][num_b]...的值。

转移方程

对于某种牌,只有使用和不使用两种选择。因此,对于1号牌:

s\[a]\[b]\[c]\[d] = max (s\[a-1]\[b]\[c]\[d]+num\[r],s\[a]\[b]\[c]\[d])

其中,r=1+a+2_b+3_c+4\*d。(注意起点编号是1,所以r要先+1)

同理,可推得总的状态转移方程:

s\[a]\[b]\[c]\[d]=max(s\[a-1]\[b]\[c]\[d],s\[a]\[b-1]\[c]\[d],s\[a]\[b]\[c-1]\[d],s\[a]\[b]\[c]\[d-1])+ num\[r]

即某状态可以由少使用一张某种牌+这个状态对应的地图上的点的分数来得到。

当然,由于输入说可能没有某种牌(a=0,b=0,...),代码实现的时候我们只能把这四种牌的转移方程拆开写。

代码

import java.util.Scanner;
public class 乌龟棋1541 {
    public static void main(String[] args){
        int n,m;
        int[] num = new int[400];
        int[] count = {0,0,0,0,0};
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for(int i = 1;i<=n;i++) num[i] = sc.nextInt();
        for(int i = 1;i<=m;i++) count[sc.nextInt()]++;
        int[][][][] s= new int[41][41][41][41];
        s[0][0][0][0] = num[1];
        for(int i = 0;i<=count[1];i++){
            for(int j = 0;j<=count[2];j++){
                for(int k = 0;k<=count[3];k++){
                    for(int l = 0;l<=count[4];l++){
                        int r = 1+i+j*2+k*3+l*4;
                        if(i!=0) s[i][j][k][l] = Math.max(s[i][j][k][l],s[i-1][j][k][l]+num[r]);
                        if(j!=0) s[i][j][k][l] = Math.max(s[i][j][k][l],s[i][j-1][k][l]+num[r]);
                        if(k!=0) s[i][j][k][l] = Math.max(s[i][j][k][l],s[i][j][k-1][l]+num[r]);
                        if(l!=0) s[i][j][k][l] = Math.max(s[i][j][k][l],s[i][j][k][l-1]+num[r]);
                    }
                }
            }
        }
        System.out.println(s[count[1]][count[2]][count[3]][count[4]]);
    }
}

T2. 樱花 多重背包

【动态规划】普及~省选的DP题 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
NOIP2010 提高组] 乌龟棋 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P1833 樱花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)