动态规划4 划分型动态规划

题目1:LintCode 108 Palindrome Partitioning II

题目2:LintCode 108 Palindrome Partitioning II

Input: "aab"
Output: 1
Explanation: Split "aab" once, into "aa" and "b", both palindrome.

将字符串每一段划分成字符串最少划分几次      划分最少,也就是回文串最长

确定状态:

最后一段回文串S[j..N-1]  需要知道S前j个字符串S[0..j-1]最少可以划分成几个字符串

dp[i]:设S前i个字符最少爱可以划分成几个字符串

最后一个回文串长度至少是1,所有j是从0到i-1

        假设:最后是一段回文串

dp[i] = min{dp[j]+1}  | S[j..i-1]是回文串     区间    [0, 1, 2,   j ... i-1, i] 

   j=0..i-1

dp[0] = 0;空串可以被分成0个回文串

怎么判断回文串:

  • 奇数   中轴外,左右两边都一样
  • 偶数   左右两边都一样

以每个子串为中心向两边扩展     时间复杂度 0(n^2)

用isPalin[i][j]:表示s[i,j]是否是回文串

dp[i] = min{dp[j]+1}  | S[j..i-1]是回文串    ====> dp[i] = min{dp[j]+1}  | isPalin[i][j]=True

答案是F[N]-1 最少划分几次    F[N]:表示以N为结尾有最少多少回文串。

时间复杂度 0(n^2)   空间复杂度 0(n^2)

 1 public class Solution {
 2     /**
 3      * @param s: A string
 4      * @return: An integer
 5      */
 6     public int minCut(String ss) {
 7         // write your code here
 8         char[] s = ss.toCharArray();
 9         int n = s.length;
10         if(n==0){
11             return 0;
12         }
13         boolean[][]  isPalin = new boolean[n][n];
14         for(int i=0; i<n; i++){
15             for(int j=0; j<n; j++){
16                 isPalin[i][j] = false;
17             }
18         }
19         int i, j, t;
20         // 判断i到j是否为回文串
21         for(t=0; t<n; t++){
22             // old-length
23             i=j=t;
24             while(i>=0 && j<n && s[i]==s[j]){
25                 isPalin[i][j] = true;
26                 i--;
27                 j++;
28             }
29
30             // even length
31             i = t;
32             j = t+1;
33             while(i>=0 && j<n && s[i]==s[j]){
34                 isPalin[i][j] = true;
35                 i--;
36                 j++;
37             }
38         }
39
40         int[] dp = new int[n+1];
41         dp[0]=0;
42         for(i=1; i<=n; i++){
43             dp[i] = Integer.MAX_VALUE;
44             for(j=0; j<i; j++){
45                 if(isPalin[j][i-1]){
46                     dp[i] = Math.min(dp[j]+1, dp[i]);
47                 }
48             }
49         }
50
51         // dp[i] = min j=0..i-1 {f[j]+1 | isPalin[j][i-1] = True}
52
53         return dp[n]-1;
54     }
55 }

题目3:LintCode 437 Copy Books

K个抄写员,可以抄写连续的若干本(每个抄写员碎度都一样每一份一页)

问最少需要多少时间可以抄写完

抄写员抄写第i本到第j本需要时间 : A[i]+A[i+1]+...+A[j]

找一种划分方式,不超过k段,使得每段所有的数字之和的最大值最小

最后一步:A[j]+..+A[N-1]

需要知道钱k-1个人最少需要多少时间抄写完前j本书(0-j-1本书)

f[k][i]:为k个抄写员最少需要多少时间抄完前i本书  (如果这边加k就表示抄写员的个数为任意多个,用k来记录状态)

f[k][i] = min {max{f[k-1][j], A[j]+A[j+1]+...+A[i-1]}}

j=0,...,j

初始条件:

  • f[0][0]=0,
  • f[0][1]=f[0][2]=...=f[0][N]=+无穷 代表不能抄,去最小值
  • f[k][0]=0;
 1 public class Solution {
 2     /**
 3      * @param pages: an array of integers
 4      * @param k: An integer
 5      * @return: an integer
 6      */
 7     public int copyBooks(int[] A, int K) {
 8         // write your code here
 9         int n = A.length;
10         if(n==0){
11             return 0;
12         }
13         if(K > n){
14             K = n;
15         }
16
17         int[][] dp = new int[K+1][n+1];
18         int i, j, k;
19
20         dp[0][0] = 0;
21         for(j=1; j<=n; j++){
22             dp[0][j] = Integer.MAX_VALUE;
23         }
24
25         int sum = 0;
26         for(k=1; k<=K; k++){
27             dp[k][0] = 0;
28             for(i=1; i<=n; i++){
29                 sum = 0;
30                 dp[k][i] = Integer.MAX_VALUE;
31                 //import j 是从j到i-1
32                 for(j=i; j>=0; j--){
33                     dp[k][i] = Math.min(dp[k][i], Math.max(dp[k-1][j], sum));
34                     if(j > 0){
35                         sum += A[j-1];
36                     }
37                 }
38             }
39             // f[k][j] = min j=0..i {max{f[k-1][j], A[j]+...+A[i-1]}}
40         }
41
42         return dp[K][n];
43     }
44 }

原文地址:https://www.cnblogs.com/JCcodeblgos/p/11520652.html

时间: 2024-10-16 16:27:22

动态规划4 划分型动态规划的相关文章

Codevs_2102_石子归并2_(划分型动态规划)

描述 http://codevs.cn/problem/2102/ 与Codevs_1048_石子归并_(划分型动态规划)相比,现在是环状的,起点任意. 2102 石子归并 2 时间限制: 10 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最

Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)

描述 http://codevs.cn/problem/1040/ 与Codevs_1017_乘积最大很像,都是划分型dp. 给出一个字符串和几个单词,要求将字符串划分成k段,在每一段中求共有多少单词(两个单词不能共享第一个字母),将每一段中的单词个数相加,求最大值. 1040 统计单词个数 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给出一个长度不超过200的由小写英文字母组成的字母串(约

Codevs_1017_乘积最大_(划分型动态规划/记忆化搜索)

描述 http://codevs.cn/problem/1017/ 给出一个n位数,在数字中间添加k个乘号,使得最终的乘积最大. 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友

划分型动态规划 之 CODE[VS] 1039 数的划分 2001年NOIP全国联赛提高组

/* dp[i][k] := 将整数i分成k份,分法种数 初始化: dp[][] = { 0 } dp[i][1] = 1 状态方程: dp[i][k] = dp[i-1][k-1] + dp[i-k][k] 思想:(引自byvoid大神的博客:https://www.byvoid.com/blog/noip-allsolutions#.E6.95.B0.E7.9A.84.E5.88.92.E5.88.86) 每种拆分方案中,最小的数为w,按照w的不同,我们可以把拆分方案分成2类: w=1,我们

划分型动态规划 之 CODE[VS] 1040 统计单词个数 2001年NOIP全国联赛提高组

/* dp[i][k] := 前i+1个字符组成的字符串,划分为k份,每份中包含的单词个数加起来总数的最大值. 初始化: dp[][] = -0x3f3f3f3f   // 注意:对于dp[i][k],若(i+1)<k,则dp[i][k]的值不存在,设为-0x3f3f3f3f.例如:dp[0][2] = -0x3f3f3f3f  dp[i][1] = val[0][i]   //注:val[i][j] := 截取原字符串[从i到j的字符(包含i和j位置的字符)]组成字符串,返回其包含的单词个数

树型动态规划练习总结

类型一.多叉树转二叉树进行资源分配 例如: * 例1. 选课:每门课可能有一门先选课,即某些课必须在另外的某节课被选之后才能选,每门课能得的学分不同,求最大学分. * 例2. 通向自由的钥匙:可以从一个房间通向另外多个房间,通过每个房间所需的花费不同,得到的价值也不同,用最小花费获得最大价值. 这种题目的特点是需要在多叉树上进行资源的分配,对不同的子树分配不同的资源,以求最大价值.可以直接在多叉树上用背包的方式求解,但是更常用的方法是用左孩子右兄弟表示法转化为二叉树. 转化之后的通用状态转移方程

区间型动态规划的记忆化搜索实现与环形动态规划的循环数组实现

区间型动态规划的典型例题是石子归并,同时使用记忆化搜索实现区间动归是一种比较容易实现的方式,避免了循环数组实现的时候一些边界的判断 n堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要消耗的代价为这两堆石子的质量之和,问最小的合并代价 状态转移方程很容易给出: f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[i][j]) 因为要计算区间和,考虑前缀和进行预处理 然后我们给出用记忆化搜索形式实现的代码,这里的记忆化搜索形式可以作为后续问题的一个模

石子归并---区间型动态规划

题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output Description 一个整数表示最小合并代价 样例输入 Sample Input 4 4 1 1 4 样

背包型动态规划

92. Backpack 可行性 https://www.lintcode.com/problem/backpack/description?_from=ladder&&fromId=16 public class Solution { /** * @param m: An integer m denotes the size of a backpack * @param A: Given n items with size A[i] * @return: The maximum size