动态规划题目总结

男娘i 2022-09-25 01:14 316阅读 0赞

题目1:

输出描述:
  1. 对于每组数据,输出一个整数,代表最长递增子序列的长度(不需要连续)。
输入例子:
  1. 2
  2. 7
  3. 89 256 78 1 46 78 8
  4. 5
  5. 6 4 8 2 17
输出例子:
  1. 3
  2. 3
  3. package dynamatic;
  4. import java.util.Scanner;
  5. public class D1 {
  6. public static void main(String[] args) {
  7. Scanner in = new Scanner(System.in);
  8. while (in.hasNextInt()) {
  9. //1.初始化
  10. int count = in.nextInt();
  11. for (int i=0; i<count; i++) {
  12. int length = in.nextInt();
  13. int[] array = new int[length];
  14. int[] values = new int[length];
  15. for (int j=0; j<length; j++) {
  16. array[j] = in.nextInt();
  17. }
  18. findMaxSLength(array, values);
  19. }
  20. }
  21. }
  22. //1.深度优先搜索
  23. public static void findMaxSLength(int[] array, int[] values) {
  24. int length = array.length;
  25. for (int i=0; i<length; i++) {
  26. if (i==0) {
  27. values[i] = 1;
  28. } else {
  29. int max = 0;
  30. for (int j=i-1; j>=0; j--) {
  31. if (array[j] < array[i]) {
  32. //2.关键的判断value[]--[1, 1, 2, 1, 3]在此基础上判断,倒推,动态更新
  33. int temp = values[j] + 1;
  34. if (temp > max) {
  35. max = temp;
  36. }
  37. }
  38. values[i] = max == 0?1:max;
  39. }
  40. }
  41. }
  42. int max=0;
  43. for (int k : values) {
  44. if (k>max) {
  45. max = k;
  46. }
  47. }
  48. System.out.print(max);
  49. }
  50. }

变化

输入例子:
  1. 2
  2. 7
  3. 89 256 78 1 46 78 8
  4. 5
  5. 6 4 8 2 17
输出例子:
  1. 1 46 78
  2. 6 8 17
  3. package dynamatic;
  4. import java.util.Scanner;
  5. import java.util.List;
  6. import java.util.ArrayList;
  7. public class D22 {
  8. public static void main(String[] args) {
  9. Scanner in = new Scanner(System.in);
  10. while (in.hasNext()) {
  11. int size = in.nextInt();
  12. for (int i = 0; i < size; i++) {
  13. int len = in.nextInt();
  14. int[] data = new int[len];
  15. for (int j = 0; j < len; j++) {
  16. data[j] = in.nextInt();
  17. }
  18. lisB(data);
  19. }
  20. }
  21. in.close();
  22. }
  23. public static void lisB(int[] array) { //dp时间复杂度(o(n2))
  24. //边界判断
  25. ArrayList<Integer> result = new ArrayList<>();
  26. if(array == null || array.length == 0) return;
  27. int length = array.length;
  28. //存储各个位置
  29. ArrayList<ArrayList<Integer>> buffer = new ArrayList<>();//每个索引下的最大子序列长度列
  30. //DFS
  31. for(int i = 0; i < length; i++) {
  32. ArrayList<Integer> temp = new ArrayList<>();
  33. temp.add(array[i]);
  34. buffer.add(temp);
  35. for(int j = i - 1; j >= 0; j--) {
  36. if(array[i] > array[j] && buffer.get(i).size() <= buffer.get(j).size()) { //j < i && array[j] < array[i]
  37. buffer.set(i,new ArrayList<Integer>(buffer.get(j))); //
  38. buffer.get(i).add(array[i]);
  39. }
  40. }
  41. if(result.size() < buffer.get(i).size()) {
  42. result = buffer.get(i);
  43. }
  44. }
  45. for (int j = 0; j < result.size(); j++) {
  46. if (j==result.size()-1) {
  47. System.out.print(result.get(j));
  48. }else {
  49. System.out.print(result.get(j)+" ");
  50. }
  51. }
  52. // return result;
  53. }
  54. }

2.求CD个数

你作为一名出道的歌手终于要出自己的第一份专辑了,你计划收录 n 首歌而且每首歌的长度都是 s 秒,每首歌必须完整地收录于一张 CD 当中。每张 CD 的容量长度都是 L 秒,而且你至少得保证同一张 CD 内相邻两首歌中间至少要隔 1 秒。为了辟邪,你决定任意一张 CD 内的歌数不能被 13 这个数字整除,那么请问你出这张专辑至少需要多少张 CD ?

输入描述:
  1. 每组测试用例仅包含一组数据,每组数据第一行为三个正整数 n, s, L 保证 n 100 , s L 10000
输出描述:
  1. 输出一个整数代表你至少需要的 CD 数量。
输入例子:
  1. 7 2 6
输出例子:
  1. 4
  2. package dynamatic;
  3. import java.util.*;
  4. public class D4CD{
  5. public static void main(String[] args){
  6. Scanner in = new Scanner(System.in);
  7. while(in.hasNext()){
  8. int n = in.nextInt();//歌曲总数
  9. int s = in.nextInt();//每首哥的时间
  10. int l = in.nextInt();//CD容量
  11. int count = (l+1)/(s+1);//每张容纳多少歌曲---都加一个空,看为整体(最大值)
  12. count = Math.min(n, count);//防止歌曲过少
  13. if(count%13==0){
  14. count--;
  15. }
  16. int sum = n/count;//需要多少CD
  17. int yu = n%count;//余数!!!!最后一个专辑剩下的歌曲
  18. /*
  19. * yu是最后一张专辑的歌曲数,如果yu是13的倍数,为了不增加专辑的数量,---没张容纳》13
  20. * 我们可以考虑从倒数第二张专辑中借一首歌,此时倒数第二张专辑的歌曲数是count-1,
  21. * 若(count-1)==yu,这种情况只能在多出一张专辑。不知道有没有讲明白?我的表述有点不到位,防止最后count-1为13倍数。
  22. *
  23. * */
  24. if(yu!=0){
  25. sum++;
  26. if(yu%13==0&&(count-yu)==1){//查看最后最后一张专辑的情况
  27. sum++;
  28. }
  29. }
  30. System.out.println(sum);
  31. }
  32. }
  33. }

3.背包问题

小萌是个WOW发烧友,每天都痴迷于他的法师号。精诚所至金石为开,小萌穿越到WOW的世界中了…
初来乍到的小萌在暴风城的小巷中,遇见了一位善良的德鲁伊。德鲁伊听了小萌的故事,打算帮助他在WOW这个世界好好活下去,于是,把自己的东西都给了小萌了…
德鲁伊的东西太多了,于是小萌去拍卖行买了几个包裹,一切妥当之后,小萌开始把东西装进包裹里。
不过,因为小萌穿越时候脑袋先着地,所以脑子不好用,每次他拿起一个物品,要不装进包里,要不就直接扔掉…
而且,一个背包一旦不往里装东西,小萌就会封上口不再用…
现在,告诉你小萌每个物品的体积,背包的个数和容量,以及小萌拿物品的顺序,你要帮助小萌求出他能拿走多少东西。

输入描述:
  1. 输入的第一行为一个整数T,代表测试数据组数。
  2. 第一行:三个正整数 NTM 分别表示物品的个数,背包的容量,背包个数。
  3. 第二行:N个数。表示每个物品的体积。
  4. 保证:
  5. 1<=N,T,M<=20,0<=vi<=30
输出描述:
  1. 对于每组数据,输出一个整数,代表小萌可以拿走的最多物品个数。
输入例子:
  1. 2
  2. 5 5 2
  3. 4 3 4 2 1
输出例子:
  1. 3
  2. package dynamatic;
  3. import java.util.Scanner;
  4. import java.util.List;
  5. import java.util.ArrayList;
  6. public class D22 {
  7. public static void main(String[] args) {
  8. Scanner in = new Scanner(System.in);
  9. while (in.hasNext()) {
  10. int size = in.nextInt();
  11. for (int i = 0; i < size; i++) {
  12. int len = in.nextInt();
  13. int[] data = new int[len];
  14. for (int j = 0; j < len; j++) {
  15. data[j] = in.nextInt();
  16. }
  17. lisB(data);
  18. }
  19. }
  20. in.close();
  21. }
  22. public static void lisB(int[] array) { //dp时间复杂度(o(n2))
  23. //边界判断
  24. ArrayList<Integer> result = new ArrayList<>();
  25. if(array == null || array.length == 0) return;
  26. int length = array.length;
  27. //存储各个位置
  28. ArrayList<ArrayList<Integer>> buffer = new ArrayList<>();//每个索引下的最大子序列长度列
  29. //DFS
  30. for(int i = 0; i < length; i++) {
  31. ArrayList<Integer> temp = new ArrayList<>();
  32. temp.add(array[i]);
  33. buffer.add(temp);
  34. for(int j = i - 1; j >= 0; j--) {
  35. if(array[i] > array[j] && buffer.get(i).size() <= buffer.get(j).size()) { //j < i && array[j] < array[i]
  36. buffer.set(i,new ArrayList<Integer>(buffer.get(j))); //
  37. buffer.get(i).add(array[i]);
  38. }
  39. }
  40. if(result.size() < buffer.get(i).size()) {
  41. result = buffer.get(i);
  42. }
  43. }
  44. for (int j = 0; j < result.size(); j++) {
  45. if (j==result.size()-1) {
  46. System.out.print(result.get(j));
  47. }else {
  48. System.out.print(result.get(j)+" ");
  49. }
  50. }
  51. // return result;
  52. }
  53. }

例4数石子:找规律

Alice 和 Bob 在玩一个取石子的游戏,有 n 堆石子,第 i 堆有 ai 个石子,两个人轮流行动,Alice 先手。每个人每次行动必须选择一堆非空的石子,拿走其中的一部分石子,谁不能行动谁就输了。

他们玩过很多次这个游戏之后都觉得太无聊了,于是决定给游戏增加一个要求:当某个人要拿第 i 堆中的石子时必须要保证第 1 .. i-1 堆的石子都已经拿光了。也就是说两个人必须先拿光第 1 堆中的石子,然后再拿第 2 堆的,第 3 堆的……以此类推。

所以现在问在这个新游戏规则下,两个人都知道石子的堆数和每堆的数量,假设两个人都绝顶聪明而且不会失误,先手的 Alice 是否一定可以必胜?

输入描述:
  1. 每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n (1 n 60) 接下来一行有 n 个整数 ai 表示第 i 堆的石子数量( 1 ai 1000000000)。
输出描述:
  1. 如果 Alice 必胜,输出 Alice,否则输出 Bob
  2. 对于样例,Alice 第一步只能拿走第 1 堆上的 1 个石子,接下来 Bob 只要拿走第 2 堆上的全部石子即可获胜。但如果两堆石子数分别是 2 1 ,那么 Alice 就必胜了。
输入例子:
  1. 2
  2. 1 2
输出例子:
  1. Bob
  2. //总结:先分析清楚题目的规律!!!!!----下笔如有神助
  3. package dynamatic;
  4. import java.util.Scanner;
  5. public class D4 {
  6. public static void main(String[] args) {
  7. Scanner s = new Scanner(System.in);
  8. boolean flag = false;// 找规律!!!12大数字前面奇数个1,--bob,偶数个----alice
  9. //只输入一次!!
  10. while (s.hasNext()) {
  11. int n = Integer.parseInt(s.nextLine());
  12. int[] a = new int[n];
  13. String[] str = s.nextLine().split(" ");
  14. int count = 0;
  15. int temp = 0;
  16. for (int i = 0; i < str.length; i++) {//得到超过1的最早位置
  17. if (Integer.parseInt(str[i]) > 1) {
  18. temp = i;
  19. break;
  20. }
  21. }
  22. for (int j = 0; j < temp; j++) {
  23. if (Integer.parseInt(str[j]) == 1) {//统计1的个数
  24. count++;
  25. }
  26. }
  27. if (count % 2 == 0) {//奇数偶数判断
  28. flag = false;
  29. break;
  30. } else {
  31. flag = true;
  32. break;
  33. }
  34. }
  35. if (flag) {
  36. System.out.println("Bob");
  37. } else {
  38. System.out.println("Alice");
  39. }
  40. }
  41. }

发表评论

表情:
评论列表 (有 0 条评论,316人围观)

还没有评论,来说两句吧...

相关阅读

    相关 动态规划(练习题目

    故事开始以前 最初的那些春天 阳光洒在杨树上 风吹来 闪银光 街道平静而温暖 钟走得好慢 那是我还不识人生之味的年代 我情窦还不开 你的衬衣如雪 盼着杨树叶

    相关 动态规划总结

    本文转载自:[风中之炎 不盛则灭][Link 1] 本文着重讨论状态是如何表示,以及方程是怎样表示的。当然,还附上关键的,有可能作为模板的代码段。但有的代码的实现是