zoukankan      html  css  js  c++  java
  • 【每天一题ACM】可重复组合数的实现,求解素数解组合Prime Solutions

    先看题目:

    Prime Solutions

           以下是一段中學時代的慘痛回憶…每當學到排列組合的單元時,最痛苦的不是分析題目,也不是帶錯公式或計算錯誤,而是所謂的「苦工題」,以下這題是個例子:

    給定正整數N與S,求出方程式(1)的所有質數解(全為質數)。

    遇到這題,通常只能硬著頭皮將每一組以「土法煉鋼」的方式一一列出,然而到了大學修過程式設計與演算法課,俾使我們能在電腦上撰寫程式輕鬆解決此問題。

     

    INPUT

    第一行一樣為測資個數

    每一行輸入正整數與正整數,N與S之間相隔一個空白鍵。

    (提示: 計算之前先考慮方程式有沒有解可以加速程式執行。)

     

    OUTPUT

    N個質數相加剛好等於S有哪些可能的組合,質數可以重複,但請由小到大排列,若無解(例如100個質數相加等於23無解)則輸出0,解可能不只一組,若有多組解時,靠左邊的數字較小的那組解則優先輸出,請參照SAMPLE OUTPUT每一筆測資的輸出之間也換一行。

     

    SAMPLE INPUT

    4

    2 5

    100 23

    3 8

    4 25

    SAMPLE OUTPUT

    2 3

    0

    2 3 3

    2 2 2 19  

    2 3 3 17

    2 3 7 13

    2 5 5 13

    2 5 7 11 

    ---------------分割线---------------

    首先先来解释一下题目,首先input第一行的4是资料的笔数,之后的2 5代表  5以内的质数取2个相加等于5,5以内的质数有 2、3,2+3=5所以输出2 3。

    本题主要考验的是质数的求解(简单)以及可重复排列数的实现(时间复杂度较大)

    根据题目需要,可以大概得到这样一个流程:

    关键的难点在于可重复排列数,其思路是设定一个标签来标记当前的位置,循环+递归。同时附加从大到小或者从小到大排列能够节省大量的运算时间。

    下面来看代码:

     1     /** 
     2     * @Title: getCombination 
     3     * @Description: 递归取得可重复排列数
     4     * @throws 
     5     */
     6     private void getCombination(ArrayList<Integer> arr, int n, int begin, ArrayList<Integer> rs, int index) {
     7         if (n == 0) {
     8             rsList.add(rs);
     9             return;
    10         }
    11         for (int i = 0; i < arr.size(); i++) {
    12 
    13             if (index == 0 || arr.get(i) >= rs.get(index - 1)) {
    14                 rs.set(index, arr.get(i));
    15                 getCombination(arr, n - 1, i + 1, clone(rs), index + 1);
    16             }
    17         }
    18     }
     1     /**
     2      * @Description: 得到质数表
     3      */
     4     private ArrayList<Integer> getAllPrimeNum(int num) {
     5         ArrayList<Integer> primeNums = new ArrayList<>();
     6         for (int i = 2; i <= num; i++) {
     7             if (isPrimeNumber(i))
     8                 primeNums.add(i);
     9         }
    10         return primeNums;
    11     }
     1     /**
     2      * @Title: isPrimeNumber
     3      * @Description: 判断是否是质数
     4      */
     5     public boolean isPrimeNumber(int number) {
     6         if (number <= 1)
     7             return false;
     8         for (int i = 2; i <= Math.sqrt(number); i++) {
     9             if (number % i == 0)
    10                 return false;
    11         }
    12         return true;
    13     }
     1     /** 
     2     * @Title: isEquals 
     3     * @Description: 判断arr所有数的和是否等于sum
     4     */
     5     public boolean isEquals(ArrayList<Integer> arr, int sum) {
     6         int temp = 0;
     7         for (int num : arr) {
     8             temp += num;
     9         }
    10         return sum == temp;
    11     }
     1 /**
     2      * @Title: sort
     3      * @Description: 无聊的排序而已,按照hashCode排序
     4      */
     5     public void sort(ArrayList<ArrayList<Integer>> rs) {
     6         for (int i = 0; i < rs.size(); i++) {
     7             for (int j = i + 1; j < rs.size(); j++) {
     8                 if (rs.get(i).hashCode() > rs.get(j).hashCode()) {
     9                     ArrayList<Integer> temp = rs.get(i);
    10                     rs.set(i, rs.get(j));
    11                     rs.set(j, temp);
    12                 }
    13             }
    14         }
    15     }
     1 /** 
     2     * @Title: primeSolution 
     3     * @Description: 程序主逻辑
     4     */
     5     public ArrayList<ArrayList<Integer>> primeSolution(int n, int num) {
     6         ArrayList<Integer> arr = getAllPrimeNum(num);
     7         ArrayList<Integer> temp = getAllPrimeNum(n);
     8         ArrayList<ArrayList<Integer>> okList = new ArrayList<>();
     9 
    10         while (temp.size() < n) {
    11             temp.add(0);
    12         }
    13         if ((!isHasResult(arr, num, n)) && n > arr.size())
    14             return null;
    15 
    16         getCombination(arr, n, 0, temp, 0);
    17         for (ArrayList<Integer> rs : rsList) {
    18             if (isEquals(rs, num) && rs.size() == n) {
    19                 okList.add(rs);
    20             }
    21         }
    22         return okList;
    23     }

    完整代码如下:

      1 import java.util.ArrayList;
      2 import java.util.Scanner;
      3 
      4 /**
      5  * @author lcc 957109587@qq.com
      6  * @version 2016年3月9日 下午9:00:43
      7  * @Description
      8  */
      9 public class PrimeSolutions {
     10     static ArrayList<ArrayList<Integer>> rsList = new ArrayList<>();
     11 
     12     public static void main(String[] args) {
     13         @SuppressWarnings("resource")
     14         Scanner scan = new Scanner(System.in);
     15         ArrayList<ArrayList> okList = new ArrayList<>();
     16         PrimeSolutions primeSolutions = new PrimeSolutions();
     17         int runtimes = scan.nextInt();
     18         for (int i = 0; i < runtimes; i++) {
     19             int n = scan.nextInt();
     20             int num = scan.nextInt();
     21             okList.add(primeSolutions.primeSolution(n, num));
     22         }
     23         for (int j = 0; j < okList.size(); j++) {
     24             if (okList.get(j) == null) {
     25                 System.out.println(0);
     26             } else {
     27                 primeSolutions.outPut(okList.get(j));
     28             }
     29             if (j < okList.size() - 1) {
     30                 System.out.println();
     31             }
     32         }
     33     }
     34 
     35     /** 
     36     * @Title: primeSolution 
     37     * @Description: 程序主逻辑
     38     */
     39     public ArrayList<ArrayList<Integer>> primeSolution(int n, int num) {
     40         ArrayList<Integer> arr = getAllPrimeNum(num);
     41         ArrayList<Integer> temp = getAllPrimeNum(n);
     42         ArrayList<ArrayList<Integer>> okList = new ArrayList<>();
     43 
     44         while (temp.size() < n) {
     45             temp.add(0);
     46         }
     47         if ((!isHasResult(arr, num, n)) && n > arr.size())
     48             return null;
     49 
     50         getCombination(arr, n, 0, temp, 0);
     51         for (ArrayList<Integer> rs : rsList) {
     52             if (isEquals(rs, num) && rs.size() == n) {
     53                 okList.add(rs);
     54             }
     55         }
     56         return okList;
     57     }
     58 
     59     /** 
     60     * @Title: getCombination 
     61     * @Description: 递归取得可重复排列数
     62     * @throws 
     63     */
     64     private void getCombination(ArrayList<Integer> arr, int n, int begin, ArrayList<Integer> rs, int index) {
     65         if (n == 0) {
     66             rsList.add(rs);
     67             return;
     68         }
     69         for (int i = 0; i < arr.size(); i++) {
     70 
     71             if (index == 0 || arr.get(i) >= rs.get(index - 1)) {
     72                 rs.set(index, arr.get(i));
     73                 getCombination(arr, n - 1, i + 1, clone(rs), index + 1);
     74             }
     75         }
     76     }
     77 
     78     /** 
     79     * @Title: clone 
     80     * @Description: 深拷贝List
     81     */
     82     private ArrayList<Integer> clone(ArrayList<Integer> rs) {
     83         ArrayList<Integer> tocopy = new ArrayList<>();
     84         for (int num : rs) {
     85             int temp = num;
     86             tocopy.add(temp);
     87         }
     88         return tocopy;
     89     }
     90 
     91     /** 
     92     * @Title: isHasResult 
     93     * @Description: 判断是否有结果条件之一
     94     */
     95     public boolean isHasResult(ArrayList<Integer> arr, int num, int n) {
     96         for (int temp : arr) {
     97             if (temp * n == num) {
     98                 return true;
     99             }
    100         }
    101         return false;
    102     }
    103 
    104     /** 
    105     * @Title: isEquals 
    106     * @Description: 判断arr所有数的和是否等于sum
    107     */
    108     public boolean isEquals(ArrayList<Integer> arr, int sum) {
    109         int temp = 0;
    110         for (int num : arr) {
    111             temp += num;
    112         }
    113         return sum == temp;
    114     }
    115 
    116     /**
    117      * @Description: 得到质数表
    118      */
    119     private ArrayList<Integer> getAllPrimeNum(int num) {
    120         ArrayList<Integer> primeNums = new ArrayList<>();
    121         for (int i = 2; i <= num; i++) {
    122             if (isPrimeNumber(i))
    123                 primeNums.add(i);
    124         }
    125         return primeNums;
    126     }
    127 
    128     /**
    129      * @Title: isPrimeNumber
    130      * @Description: 判断是否是质数
    131      */
    132     public boolean isPrimeNumber(int number) {
    133         if (number <= 1)
    134             return false;
    135         for (int i = 2; i <= Math.sqrt(number); i++) {
    136             if (number % i == 0)
    137                 return false;
    138         }
    139         return true;
    140     }
    141 
    142     /**
    143      * @Title: sort
    144      * @Description: 无聊的排序而已,按照hashCode排序
    145      */
    146     public void sort(ArrayList<ArrayList<Integer>> rs) {
    147         for (int i = 0; i < rs.size(); i++) {
    148             for (int j = i + 1; j < rs.size(); j++) {
    149                 if (rs.get(i).hashCode() > rs.get(j).hashCode()) {
    150                     ArrayList<Integer> temp = rs.get(i);
    151                     rs.set(i, rs.get(j));
    152                     rs.set(j, temp);
    153                 }
    154             }
    155         }
    156     }
    157 
    158     /**
    159      * @Description: 按照格式输出rs
    160      */
    161     public void outPut(ArrayList<ArrayList<Integer>> rs) {
    162         sort(rs);
    163         for (int i = 0; i < rs.size(); i++) {
    164             for (int temp : rs.get(i))
    165                 System.out.print(temp + " ");
    166             System.out.println();
    167         }
    168     }
    169 }

    欢迎指正!

  • 相关阅读:
    试题 E: 迷宫
    对拍程序
    人群中钻出个光头
    HDU-魔咒词典(字符串hash)
    第八集 你明明自己也生病了,却还是要陪着我
    智力问答 50倒计时
    数据结构
    LeetCode刷题 fIRST MISSING POSITIVE
    LeetCode Best to buy and sell stock
    LeetCode Rotatelmage
  • 原文地址:https://www.cnblogs.com/Linccy/p/5376331.html
Copyright © 2011-2022 走看看