题目1251:序列分割(DFS+剪枝)

来源:互联网 发布:梅原大吾背水逆转 知乎 编辑:程序博客网 时间:2024/06/05 03:27

题目描述:

一个整数数组,长度为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。

样例输入:
95 2 1 5 2 1 5 2 141 2 3 40
样例输出:
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) {//找到一个组合的值为maxreturn 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;//剪枝在无法找到构成maxif (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();}}}



0 0