題目1251:序列分割(DFS+剪枝)
阿新 • • 發佈:2019-02-09
- 題目描述:
-
一個整數陣列,長度為n,將其分為m份,使各份的和相等,求m的最大值
比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1;
{3,6}{2,4,3} m=2
{3,3}{2,4}{6} m=3 所以m的最大值為3。
- 輸入:
-
存在多組資料,每組資料一定行為一個正整數n(n<=64),第二行為n個數字。當n為0時,測試結束。
- 輸出:
-
輸出最大值m。
- 樣例輸入:
-
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
- 樣例輸出:
-
4 2
import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.PrintWriter; import java.io.OutputStreamWriter; import java.io.StreamTokenizer; import java.util.Arrays; class Main { public static final boolean DEBUG = false; public static int N = 100; public BufferedReader cin; public PrintWriter cout; public StreamTokenizer tokenizer; public int[] numArr; public int n, sum; public boolean[] vis; public void init() { try { if (DEBUG) { cin = new BufferedReader(new InputStreamReader( new FileInputStream("d:\\OJ\\uva_in.txt"))); } else { cin = new BufferedReader(new InputStreamReader(System.in)); } cout = new PrintWriter(new OutputStreamWriter(System.out)); tokenizer = new StreamTokenizer(cin); } catch (Exception e) { e.printStackTrace(); } } public String next() { try { tokenizer.nextToken(); if (tokenizer.ttype == StreamTokenizer.TT_EOF) return null; else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) { return String.valueOf((int) tokenizer.nval); } return null; } catch (Exception e) { e.printStackTrace(); return null; } } public boolean input() { String s = next(); if (s == null) return false; n = Integer.parseInt(s); if (n == 0) return false; numArr = new int[n]; vis = new boolean[n]; sum = 0; for (int i = 0; i < n; i++) { numArr[i] = Integer.parseInt(next()); sum += numArr[i]; } return true; } public boolean Try(int m) { if (sum % m != 0) return false; Arrays.fill(vis, false); return dfs(sum / m, m, m, 0); } public boolean dfs(int cnt, int max, int re, int s) { if (cnt == 0) return true; if (re == 0) { //找到一個組合的值為max return dfs(cnt - 1, max, max, 0); } for (int i = s; i < n; i++) { if (vis[i] || re - numArr[i] < 0) continue; vis[i] = true; if (dfs(cnt, max, re - numArr[i], i + 1)) return true; vis[i] = false; //剪枝在找到一個組合的值為max後,接下來的不能成立 if (re - numArr[i] == 0) break; //剪枝在無法找到構成max if (max == re) break; //剪枝在未選擇時,跳過相同的 while (i + 1 < n && numArr[i + 1] == numArr[i]) i++; } return false; } public void solve() { Arrays.sort(numArr); for (int start = 0, end = numArr.length - 1; start < end; start++, end--) { int tmp = numArr[start]; numArr[start] = numArr[end]; numArr[end] = tmp; } int m = numArr[0]; while (!Try(m)) m++; cout.println(sum / m); cout.flush(); } public static void main(String[] args) { Main solver = new Main(); solver.init(); while (solver.input()) { solver.solve(); } } }