今日やったのはこれ。
http://www.topcoder.com/stat?c=problem_statement&pm=8784&rd=12178
まず、ワンコは全然関係無いのでスルー。ある数値群で50を作れるのがポイントかなーとか思ったけど順列の組み合わせはたかだか5万程度(8要素しか無いから)なので全部ナイーブに見ちゃえ。
import java.util.Arrays; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; public class SymmetricPie { public class Permutation implements Iterable<int[]> { private final int size; /** * <p>順列を表すクラスのコンストラクタ。反復子が返す配列の要素数を指定する。 * @param size 順列の要素数(10程度が妥当な最大値) * @throws IllegalArgumentException 引数(順列の要素数)が0以下の場合 */ public Permutation(int size) { if (size <= 0) throw new IllegalArgumentException(); this.size = size; } public Iterator<int[]> iterator() { return new Iter(size); } private class Iter implements Iterator<int[]> { private final int[] source; private boolean isFirst = true; private Iter(int size) { source = new int[size]; for(int i = 0; i < size; ++i) { source[i] = i; } } /** * <p>反復子がまだ順列を返しうるか調べる。 * 本メソッドは{@link Iter#next()}呼び出し前に必ず1回ずつ実行する必要がある。 * @return 順列が存在する場合はtrue */ public boolean hasNext() { if (isFirst) { isFirst = false; return true; } int n = source.length; for (int i = n - 1; i > 0; i--) { if (source[i - 1] < source[i]) { int j = n; while (source[i - 1] >= source[--j]); swap(source, i - 1, j); reverse(source, i, n); return true; } } reverse(source, 0, n); return false; } /** * <p>次の順列を表すint型配列を返す。 * <p>このメソッドが返す参照は常に同じ配列に対する参照である。 * このため配列の要素を変更したり次回の{@link Iter#next()}呼び出し後も参照する場合は、 * クラスの呼び出し側が配列のクローンを生成して利用する必要がある。 * @return 順列を表すint型配列 */ public int[] next() { return source; } public void remove() { throw new UnsupportedOperationException(); } private void swap(int[] is, int i, int j) { int t = is[i]; is[i] = is[j]; is[j] = t; } private void reverse(int[] is, int s, int t) { while (s < --t) swap(is, s++, t); } } } public int getLines(int[] dogs) { int cnt = dogs.length; int maxLines = 0; Permutation permutations = new Permutation(cnt); int[] combi = new int[cnt]; int l = 0; for (int[] permutation : permutations) { for (int k = 0; k < permutation.length; k++) { combi[k] = dogs[permutation[k]]; } HashSet<Integer> combiSet = new HashSet<Integer>(); int total = 0; int lines = 0; for (int j = 0; j < cnt; j++) { total += combi[j]; if (total == 100) { break; } if (total == 50) { lines++; } if (combiSet.contains(total - 50)) { lines++; } combiSet.add(total); } if (maxLines < lines) { maxLines = lines; } l++; } return maxLines; } }==
permutationsのロジックを思いつかずにハマった。ちゃんと身につけるToDo行き。
今回は http://topcoder.g.hatena.ne.jp/eller/20090831/1251723649 の「IterableなJava版next_permutation」を使わせてもらいました。
0 件のコメント:
コメントを投稿