2017年網易游戲的一道編程題,大致意思是滿足組合攻擊技能,必須是所選擇時技能的和為m(m>0),且所選的這些技能的乘積最大:
分解后主解決兩個問題:
其一:求數組中和為m的所有子數組;
其二:在滿足一的條件下,求所有子數組的最大值;
主要考察的還是如何求數組中和為m的所有子數組:
如:數組[1,2,3,4,5,6],m=7時,滿足條件的子數組有[1,2,4],[3,4],[2,5],[1,6];
主要使用回溯法解決該問題,思路以后補上:
package com.didi; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main1 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); while(scanner.hasNext()){ int n = scanner.nextInt(); int sum = scanner.nextInt(); int[] arr = new int[n]; for(int i=0;i<n;i++){ arr[i] = scanner.nextInt(); } Arrays.sort(arr);//必須先排序 ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>(); boolean[] visited = new boolean[n]; backTrack(arr, visited, 0, 0, sum, lists);//求和為sum的所有組合數 System.out.println(lists); System.out.println(lists.size());//求和為sum的所有組合數 System.out.println(maxFighting(lists));//求最大組合攻擊力 } } //求非降序序列中和為定值的所有組合,必須為非降序序列,否則會重復,如{2 4 2 5 4 1 6}-->[[2, 4, 4], [2, 2, 5, 1], [4, 2, 4], [4, 5, 1], [5, 4, 1]],統計有重復只是順序不一樣 public static void backTrack(int[] input, boolean[] visited, int n, int sum, int key, ArrayList<ArrayList<Integer>> lists){ if(sum>key) return; if(sum==key){ ArrayList<Integer> list = new ArrayList<Integer>(); for(int j=0; j<=n; j++){ if(visited[j]){ list.add(input[j]); } } lists.add(list); return; } if(n>=input.length) return; for(int i=n;i<input.length-1;i++){ if(!visited[i]){ sum += input[i]; visited[i] = true; backTrack(input, visited, i+1, sum, key, lists); visited[i] = false; sum -= input[i]; while(i<input.length-1&&input[i]==input[i+1]) i++; } } } public static int maxFighting(ArrayList<ArrayList<Integer>> lists){ int size = lists.size(); if(lists==null||size==0) return -1; int maxMultipy = Integer.MIN_VALUE; int multipy = 1; for(int i=0;i<size;i++){ ArrayList<Integer> list = lists.get(i); for(int j=0;j<list.size();j++){ multipy *=list.get(j); } if(multipy>maxMultipy){ maxMultipy = multipy; } multipy = 1; } return maxMultipy; } }