1.写在前面的话

多动脑对身体有好处,我也不知道写的对不对,不当之处请指正。

2.题目

链接(不知道后面对不对):罪犯转移_牛客题霸_牛客网

C市现在要转移一批罪犯到D市,C市有n名罪犯,按照入狱时间有顺序,另外每个罪犯有一个罪行值,值越大罪越重。现在为了方便管理,市长决定转移入狱时间连续的c名犯人,同时要求转移犯人的罪行值之和不超过t,问有多少种选择的方式(一组测试用例可能包含多组数据,请注意处理)?

输入描述:第一行数据三个整数:n,t,c(1≤n≤2e5,0≤t≤1e9,1≤c≤n),第二行按入狱时间给出每个犯人的罪行值ai(0≤ai≤1e9)。输出描述:一行输出答案。

输入:

3 100 2
1 2 3

输出:2

较大数据输入:

12023 222720 2320

106 22 28 77 88 9 59 12 18 109 102 19 58 124 14 0 31 121 120 8 77 1 22 14 76 18 43 61 46 36 113 26 61 48 62 13 30 35 30 122 76 23 70 1 25 18 15 90 108 127 82 104 79 117 0 41 110 32 67 44 26 69 43 96 63 119 63 96 112 55 97 98 117 27 114 121 118 19 5 36 111 65 6 12 59 0 30 109 62 87 48 111 88 112 31 109 98 27 27 32 122 125 107 75 115 77 117 111 90 118 126 100 21 5 36 126 23 60 25 45 82 125 20 84 103 82 81 65 16 125 42 103 106 6 97 35 81 81 101 11 123 122 56 123 16 107 12 86 118 96 122 72 90 5 48 29 76 1 20 101 3 105 86 46 65 127 19 31 16 68 72 20 82 5 69 10 119 92 1 16 127 124 18 26 97 109 58 14 4 65 114 99 19 99 19 44 41 8 40 58 73 116 7 117 112 63 48 119 31 93 58 52 10 37 44 105 103 48 102 123 90 63 62 12 124 94 22 18 4 96 76 113 45 9 126 102 111 28 96 76 46 72 68 85 108 118 66 110 47 0 0 50 126 88 47 20 88 64 54 37 55 4 100 109 42 49 56 127 84 63 28 78 87 94 37 6 64 38 84 39 57 125 55 64 124 111 103 99 113 8 22 44 25 18 104 53 82 13 112 17 4 11 92 14 80 108 24 106 76 47 38 78 92 77 38 76 81 92 121 121 27 71 67 2 118 69 16 9 58 73 17 6 126 126 89 43 88 0 26 39 28 96 73 66 42 30 3 119 108 101 38 107 56 20 40 74 25 48 99 52 126 61 74 115 64 106 35 88 37 6 33 37 5 27 89 9 27 26 111 21 74 64 24 111 52 26 43 23 74 7 112 38 116 40 19 101 127 46 78 123 18 55 5 77 113 50 77 20 47 122 35 37 105 8 46 23 24 80 57 64 8 27 55 54 40 102 87 38 27 78 107 26 4 77 70 64 96 26 48 73 31 59 116 7 24 23 67 77 19 2 2 54 111 56 119 48 44 2 123 84 60 75 116 91 122 31 9 14 18 54 5 49 64 14 87 76 82 66 67 60 89 95 109 74 39 34 69 60 10 100 4 68 26 100 85 97 39 11 106 99 4 103 6 9 57 59 114 114 31 111 51 98 44 100 55 59 110 35 65 92 107 83 10 18 66 113 100 67 19 61 122 117 77 52 93 38 47 91 71 120 39 47 91 57 20 64 66 88 127 73 86 62 25 40 38 14 91 119 74 15 28 73 15 63 6 51 59 77 100 73 125 55 53 49 11 47 109 103 13 122 59 79 51 83 113 97 20 82 19 87 92 116 110 62 42 92 104 59 44 72 10 17 27 52 13 66 112 30 28 37 40 24 41 91 69 11 63 88 108 0 113 46 117 61 63 107 28 65 96 16

输出结果:9704

3.读懂题意

第一行的3个数字n t c,分别表示n个罪犯、所有转移罪犯可容忍罪行值最大限制t、转移罪犯数c;第二行数据为每个罪犯的罪行值(可以将下标看作罪犯编号,每个值为罪行值);注意转移时,c个罪犯的编号必须是连续的。

4.注意单个罪行值超过最大时的影响

由于要转移连续的C个罪犯,当一个罪犯的罪行值超过t,将影响他前后c-1个罪犯(连坐)不能转移。

5.动态规划相关

由于容忍的最大罪行值为t,每选择一个罪犯进行转移时,可容忍的最大罪行值都会减小(动态变化,类似往瓶子里装石头一样),在动态减小过程中,若下一位罪犯的罪行值超过了可容忍的最大罪行值(动态变化的),则对于当前连续的c个罪犯后面的罪犯值,无需再进行判断(大数据量时可避免不少计算,应该是这点跟主旨动态规划比较相关),当前这c个罪犯的选法不符合要求;若都符合条件,则该选法为正确选法之一。

若不使用上述思想,而是普通的逻辑算法(累加c个罪行值,再判断),虽然也能得出正确结果,但当数据量较大时,运行时间将不达标;附加普通方法如下。

public static void main(String[] args) throws Exception{Scanner in = new Scanner(System.in);while(in.hasNextLine()){String paramStr = in.nextLine();int n = Integer.parseInt(paramStr.split(" ")[0]);int t = Integer.parseInt(paramStr.split(" ")[1]);int c = Integer.parseInt(paramStr.split(" ")[2]);int[] weightArray = new int[n];if(in.hasNextLine()){String dataStr = in.nextLine();String[] numStrArray = dataStr.split(" ");for(int i=0; i<numStrArray.length && i<n; i++){weightArray[i] = Integer.parseInt(numStrArray[i]);}}long startTime = System.currentTimeMillis();int transferSelectNum = calcTransferNormal(n, t, c, weightArray);System.out.println("计算花费时间:" + (System.currentTimeMillis()-startTime));System.out.println(transferSelectNum);}
}private static int calcTransferNormal(int n, int t, int c, int[] weightArray) {int selectTotal = 0; // 选法数量for (int startIndex = 0; startIndex <= n - c; startIndex++) { // 遍历n-c次int weightTotal = 0; // 累计权重值for (int k = 0; k < c; k++) {weightTotal += weightArray[startIndex + k];}if(weightTotal <= t){selectTotal++;}}return selectTotal;
}

普通方法虽然也能得到正确答案,但当数据量过大时,运行会很长,在牛客网上提交会运行超时。

略带动态规划思想的方法如下:

    public static void main(String[] args) throws Exception{Scanner in = new Scanner(System.in);while(in.hasNextLine()){String paramStr = in.nextLine();int n = Integer.parseInt(paramStr.split(" ")[0]);int t = Integer.parseInt(paramStr.split(" ")[1]);int c = Integer.parseInt(paramStr.split(" ")[2]);int[] weightArray = new int[n];if(in.hasNextLine()){String dataStr = in.nextLine();String[] numStrArray = dataStr.split(" ");for(int i=0; i<numStrArray.length && i<n; i++){weightArray[i] = Integer.parseInt(numStrArray[i]);}}long startTime = System.currentTimeMillis();// int transferSelectNum = calcTransferNormal(n, t, c, weightArray);int transferSelectNum = calcTransfer(n, t, c, weightArray);System.out.println("计算花费时间:" + (System.currentTimeMillis()-startTime));System.out.println(transferSelectNum);}}private static int calcTransfer(int n, int t, int c, int[] weightArray) {int selectTotal = 0;for (int startIndex = 0; startIndex <= n - c; startIndex++) { // 遍历n-c次if (weightArray[startIndex] > t) { // 单个罪犯罪行值超过最大t,需跳过后续c-1,注意++需多减1startIndex = startIndex + c - 2;continue;}if(satisfyCondition(weightArray, startIndex+1, startIndex + c-1, t-weightArray[startIndex])){selectTotal++;}}return selectTotal;}private static boolean satisfyCondition(int[] weightArray, int startIndex, int endIndex, int maxWeight) {// 动态规划相关,随着已选择罪行值的增加,可容忍罪行值减少for(int i=startIndex; i<=endIndex; i++){if(weightArray[i] > maxWeight){ // 当c位罪犯中的某一位罪行值超过可容忍最大值return false;}else{maxWeight -= weightArray[i]; // 前一个罪行值已算入,最大可容忍罪行值减少}}return true;}

6.借鉴别人的新解法

先计算前c个连续罪犯的罪行值,利用连续做文章,若要连续,每次都是整段移动,相当于移除前一个值,再加入后一个值,再进行判断;这种解法运行效率很高,虽然c个罪犯的累计罪行值是动态变化的,但没有很好的体现动态规划的思想。

    public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) {String paramStr = in.nextLine();int n = Integer.parseInt(paramStr.split(" ")[0]);int t = Integer.parseInt(paramStr.split(" ")[1]);int c = Integer.parseInt(paramStr.split(" ")[2]);int[] weightArray = new int[n];if (in.hasNextLine()) {String dataStr = in.nextLine();String[] numStrArray = dataStr.split(" ");for (int i = 0; i < numStrArray.length && i < n; i++) {weightArray[i] = Integer.parseInt(numStrArray[i]);}}int transferSelectNum = calcTransferNew(n, t, c, weightArray);System.out.println(transferSelectNum);}}/*** 转移罪犯新解法* 先计算前c个罪犯的总罪行值,后面后移这c个罪犯的下标,相当于加入后一个罪犯,移除最前的罪犯,再次计算判断  */private static int calcTransferNew(int n, int t, int c, int[] weightArray) {int selectWeightSum = 0; // 所有选择罪犯的罪行值总和int selectTotal = 0; // 多少种选法// 第一种选法,前c个罪犯for(int i=0; i<c; i++){selectWeightSum += weightArray[i];}if(selectWeightSum <= t){selectTotal += 1;}// 连续的c个罪犯下标往后移,移除最前,加上最后for (int k = c; k < n; k++) { // 遍历n-c次selectWeightSum -= weightArray[k-c]; // 移除最前的罪行值selectWeightSum += weightArray[k]; // 加上新加入的罪行值if(selectWeightSum <= t){selectTotal++;}}return selectTotal;}

动态规划-罪犯转移问题相关推荐

  1. 罪犯转移 用滑动窗口做,一次AC

    罪犯转移 热度指数:2731时间限制:1秒空间限制:32768K 本题知识点:  动态规划 算法知识视频讲解 题目描述 C市现在要转移一批罪犯到D市,C市有n名罪犯,按照入狱时间有顺序,另外每个罪犯有 ...

  2. Wooden Sticks POJ - 1065(最大上升子序列+动态规划状态转移思维)

    题意: 给你n个木棍的长度和重量,让其成为上升序列,如果不能达到,就需要重新一分钟设置. a)第一个木棍的准备时间为1分钟. b)在处理长度为l和重量为w的棒之后,如果l <= l'并且w &l ...

  3. KMP算法的动态规划解说

    理解我接下来所说的东西,需要大家懂得简单的动态规划. KMP大家都不陌生了,但是其中计算next数组总是搞不明白,我想有很多人和我一样.所以这里用动态规划的思路去描述一下这个问题. 模式串P=c[1] ...

  4. 动态规划:记忆化搜索

    记忆化搜索和递推都是为了解决子问题重复计算而产生的 虽然动态规划的转移图是一个DAG,但是一个状态可以被其他的状态复用多次 因此为了提高动态规划的效率,记忆化搜索便产生了 但是有时候,状态转移图是不容 ...

  5. 一看就懂的动态规划入门教程

    今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的讲解非常不一样,令我眼前一亮,于是转载一下下--- (说明一下,本人非常痛恨教材公式定理漫天飞,实际的讲解却讲得非常枯涩难懂,这种 ...

  6. 动态规划专题 01背包问题详解【转】

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

  7. 动态规划——矩阵中的最短路径长度

    文章出处:极客时间<数据结构和算法之美>-作者:王争.该系列文章是本人的学习笔记. 题目 假设我们有一个 n 乘以 n 的矩阵 w[n][n].矩阵存储的都是正整数.棋子起始位置在左上角, ...

  8. 【数据结构与算法】【算法思想】动态规划

    贪心算法 回溯算法 分治算法 动态规划 贪心:一条路走到黑,就一次机会,只能哪边看着顺眼走哪边 回溯:一条路走到黑,无数次重来的机会,还怕我走不出来 (Snapshot View) 动态规划:拥有上帝 ...

  9. 【动态规划模型】金矿模型理解动态规划!(精彩的故事)

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

最新文章

  1. 不懂编程可以自学python吗-关于大学小白如何学习Python语言程序设计
  2. Jsp(Java Server Pages)简介
  3. 如何保证Linux服务器的安全
  4. ICE简单介绍及使用示例
  5. Java-Web机试练习题一、后台管理系统——管理员管理模块
  6. python比较两张图片是否一样_opencv_判断两张图片是否相同
  7. RabbitMQ消息队列———安装(一)
  8. js判断ipad还是安卓_最近iPad做电子笔记很流行?综合分析你知道的所有笔记方式。...
  9. 多行文字或者单行文字的垂直居中解决方案
  10. DevOps实践教程 华为云 系列教程2021 合集
  11. Linux系统提高编辑效率的vim工具重要知识
  12. 关于PC套件显示红外连接出现问题而导致连接不上的解决方案(zz)
  13. spconv编译与安装
  14. Hyperledger Fabric Service Discovery CLI(服务发现命令行工具)学习笔记
  15. Web功能测试主要包括哪些方面?
  16. python怎么读汉字翻译拼音_python把汉字转换成拼音实现程序
  17. 你知道吗?计算机界也有诺贝尔奖!
  18. 2021年制冷与空调设备运行操作考试题及制冷与空调设备运行操作证考试
  19. 数据挖掘:实用案例分析 下载_真经阁丨萌低龄,超实用“萌系”呈现技巧及设计案例分析...
  20. 无线网关服务器搭建教程,【树莓派】简易LoRa网关搭建+服务器设置一条龙教程(the things network)...

热门文章

  1. 运算放大器积分电路原理
  2. 可行加权最小二乘法_最小二乘法和加权最小二乘法
  3. 第五十三周总结——云文档开发一周总结
  4. idea中java件带锁标记_java中的锁
  5. mysql fsync_用一分钟了解: fsync这个系统调用!
  6. gitHub Action - workflow 概念和基本操作
  7. 速读原著-TCP/IP(BOOTP 的分组格式)
  8. web渗透之jwt 安全问题
  9. sigaction 使用
  10. Linux errno错误信息大全