zoukankan      html  css  js  c++  java
  • 微软算法100题21 数列中所有和为特定值的组合

    第21 题
    编程求解:
    输入两个整数n 和m,从数列1,2,3.......n 中随意取几个数,
    使其和等于m ,要求将其中所有的可能组合列出来

    思路:典型的01背包问题,按照背包问题的思路,可以将问题:f(n,m),分解为f(n-1,m)和[f(n-1,m-n),n]两个子问题

    就是N个数里面和等于M的元素组合,一定包含N-1个数里所有和为M的组合,再加上N-1个数里所有和为M-N的组合,再加上N这个元素

    为了记录所有符合要求的元素,可以用一个大小为N的整数数组来标记数列1到N的元素状态,如果元素N符合要求,则marks[n-1]=1,否则marks[n-1]=0

    这里需要考虑的是何时标记为1?何时标记为0?  对于子问题f(n-1,m-n)来说,我们需要把元素N标记为1,因为如果f(n-1,m-n)有符合要求的元素的话,元素N也符合要求。对于子问题f(n-1,m)来说,我们需要把元素N标记为0,即元素N不符合要求,因为子问题f(n-1,m)已经将N排除在外了。

    这里我们使用递归来解决背包问题,最佳方法仍是动态规划,这个留到以后。

     1 package com.rui.microsoft;
     2 
     3 
     4 /**
     5  * 第21 题
     6 编程求解:
     7 输入两个整数n 和m,从数列1,2,3.......n 中随意取几个数,
     8 使其和等于m ,要求将其中所有的可能组合列出来
     9  *
    10  */
    11 public class Test21_01Bag {
    12 
    13     public static void main(String[] args) {
    14         int m = 15;
    15         int n = 10;
    16         int[] marks = new int[n];
    17         Test21_01Bag.find(n, m, marks);
    18     }
    19     
    20     public static void print(int[] marks){
    21         for(int i = 0; i < marks.length; i++){
    22             if(marks[i] == 1){
    23                 System.out.print(" " + (i+1));
    24             }
    25         }
    26         System.out.println("");
    27     }
    28     
    29     public static void find(int n, int m, int[] marks){
    30         //n和m的值不能小于1,否则从该次递归返回
    31         if(n<1 || m<1)return;
    32         //如果n大于m,则应该重置n为m,因为大于m的元素肯定不符合要求
    33         if(n>m)n=m;
    34         if(n==m){
    35             //如果n==m,说明当前n元素是符合条件的
    36             marks[n-1]=1;
    37             //打印该组合
    38             print(marks);
    39             //打印完毕,将该元素n的状态恢复初始值
    40             marks[n-1]=0;
    41         }
    42         
    43         //先标记元素n,然后递归解决子问题f(n-1,m-n)
    44         //因为子问题f(n-1,m-n)所包含的符合条件的元素组合再加上元素n才能得到最终解,所以元素n标记为1
    45         marks[n-1]=1;
    46         find(n-1,m-n,marks);
    47         
    48         //先标记元素n,然后递归解决子问题f(n-1,m)
    49         //此时元素n已经被排除在子问题f(n-1,m)之外了,所以将其标记为0
    50         marks[n-1]=0;
    51         find(n-1,m,marks);
    52     }
    53 }
  • 相关阅读:
    POJ 3276 Face The Right Way
    POJ 3061 Subsequence
    HDU 2104 hide handkerchief
    GCJ Crazy Rows
    HDU 1242 Rescue
    激光炸弹:二维前缀和
    I Hate It:线段树:单点修改+区间查询
    承压计算:模拟+double
    等差素数列:线性筛+枚举
    Period :KMP
  • 原文地址:https://www.cnblogs.com/aalex/p/4908362.html
Copyright © 2011-2022 走看看