2, 4, 10, 16, 31, 47, 76, 111, 166, 235
노트
우리는 그래프 고려하면 G
꼭지점 0
에 n
, 다음 경기 두 숫자에 가입하고 가장자리 텐서 전원이 G^n
정점이 (x_0, ..., x_{n-1})
직교 전원 구성 {0, ..., n}^n
과 일치하는 튜플 사이의 가장자리를. 관심있는 그래프 는 가능한 "카운팅 배열"에 해당하는 정점 G^n
에 의해 유도 된 하위 그래프입니다 .
따라서 첫 번째 하위 작업은 해당 정점을 생성하는 것입니다. 순진한 접근 방식은 2^{2n-1}
문자열 또는의 순서로 열거 됩니다 4^n
. 그러나 대신 카운팅 배열의 첫 번째 차이 배열을 살펴보면 3^n
가능성 만 있다는 것을 알 수 있으며 첫 번째 차이에서 0 번째 차이의 요소가 0
또는 보다 큼 n
.
그런 다음 최대 독립 세트를 찾고 싶습니다. 하나의 정리와 두 가지 휴리스틱을 사용하고 있습니다.
- 정리 : 독립된 그래프 집합의 최대 독립 집합은 최대 독립 집합의 합입니다. 따라서 그래프를 연결되지 않은 구성 요소로 분류하면 문제를 단순화 할 수 있습니다.
- 휴리스틱 :
(n, n, ..., n)
최대 독립 세트에 있다고 가정합니다 . 일치하는 가장 작은 정수인 정점의 상당히 큰 {m, m+1, ..., n}^n
부분 m
이 있습니다 n
.(n, n, ..., n)
해당 파편 밖에서는 일치하는 것이 없습니다.
- 휴리스틱 : 최저 정점을 선택하는 욕심 많은 접근 방식을 취하십시오.
이 발견 내 컴퓨터 111
에 대한 n=8
16초에 166
대한 n=9
8에 대한 분, 235
대한 n=10
2에 대한 시간.
암호
다른 이름으로 저장하고 다른 이름 PPCG54354.java
으로 컴파일 javac PPCG54354.java
하고 다음으로 실행하십시오 java PPCG54354
.
import java.util.*;
public class PPCG54354 {
public static void main(String[] args) {
for (int n = 1; n < 20; n++) {
long start = System.nanoTime();
Set<Vertex> constructive = new HashSet<Vertex>();
for (int i = 0; i < (int)Math.pow(3, n-1); i++) {
int min = 0, max = 1, diffs[] = new int[n-1];
for (int j = i, k = 0; k < n-1; j /= 3, k++) {
int delta = (j % 3) - 1;
if (delta == -1) min++;
if (delta != 1) max++;
diffs[k] = delta;
}
for (; min <= max; min++) constructive.add(new Vertex(min, diffs));
}
// Heuristic: favour (n, n, ..., n)
Vertex max = new Vertex(n, new int[n-1]);
Iterator<Vertex> it = constructive.iterator();
while (it.hasNext()) {
Vertex v = it.next();
if (v.matches(max) && !v.equals(max)) it.remove();
}
Set<Vertex> ind = independentSet(constructive, n);
System.out.println(ind.size() + " after " + ((System.nanoTime() - start) / 1000000000L) + " secs");
}
}
private static Set<Vertex> independentSet(Set<Vertex> vertices, int dim) {
if (vertices.size() < 2) return vertices;
for (int idx = 0; idx < dim; idx++) {
Set<Set<Vertex>> p = connectedComponents(vertices, idx);
if (p.size() > 1) {
Set<Vertex> ind = new HashSet<Vertex>();
for (Set<Vertex> part : connectedComponents(vertices, idx)) {
ind.addAll(independentSet(part, dim));
}
return ind;
}
}
// Greedy
int minMatches = Integer.MAX_VALUE;
Vertex minV = null;
for (Vertex v0 : vertices) {
int numMatches = 0;
for (Vertex vi : vertices) if (v0.matches(vi)) numMatches++;
if (numMatches < minMatches) {
minMatches = numMatches;
minV = v0;
}
}
Set<Vertex> nonmatch = new HashSet<Vertex>();
for (Vertex vi : vertices) if (!minV.matches(vi)) nonmatch.add(vi);
Set<Vertex> ind = independentSet(nonmatch, dim);
ind.add(minV);
return ind;
}
// Separates out a set of vertices which form connected components when projected into the idx axis.
private static Set<Set<Vertex>> connectedComponents(Set<Vertex> vertices, final int idx) {
List<Vertex> sorted = new ArrayList<Vertex>(vertices);
Collections.sort(sorted, new Comparator<Vertex>() {
public int compare(Vertex a, Vertex b) {
return a.x[idx] - b.x[idx];
}
});
Set<Set<Vertex>> connectedComponents = new HashSet<Set<Vertex>>();
Set<Vertex> current = new HashSet<Vertex>();
int currentVal = 0;
for (Vertex v : sorted) {
if (!match(currentVal, v.x[idx]) && !current.isEmpty()) {
connectedComponents.add(current);
current = new HashSet<Vertex>();
}
current.add(v);
currentVal = v.x[idx];
}
if (!current.isEmpty()) connectedComponents.add(current);
return connectedComponents;
}
private static boolean match(int a, int b) {
return a <= 2 * b && b <= 2 * a;
}
private static class Vertex {
final int[] x;
private final int h;
Vertex(int[] x) {
this.x = x.clone();
int _h = 0;
for (int xi : x) _h = _h * 37 + xi;
h = _h;
}
Vertex(int x0, int[] diffs) {
x = new int[diffs.length + 1];
x[0] = x0;
for (int i = 0; i < diffs.length; i++) x[i+1] = x[i] + diffs[i];
int _h = 0;
for (int xi : x) _h = _h * 37 + xi;
h = _h;
}
public boolean matches(Vertex v) {
if (v == this) return true;
if (x.length != v.x.length) throw new IllegalArgumentException("v");
for (int i = 0; i < x.length; i++) {
if (!match(x[i], v.x[i])) return false;
}
return true;
}
@Override
public int hashCode() {
return h;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof Vertex) && equals((Vertex)obj);
}
public boolean equals(Vertex v) {
if (v == this) return true;
if (x.length != v.x.length) return false;
for (int i = 0; i < x.length; i++) {
if (x[i] != v.x[i]) return false;
}
return true;
}
@Override
public String toString() {
if (x.length == 0) return "e";
StringBuilder sb = new StringBuilder(x.length);
for (int xi : x) sb.append(xi < 10 ? (char)('0' + xi) : (char)('A' + xi - 10));
return sb.toString();
}
}
}
L1[i]/2 <= L2[i] <= 2*L1[i]
합니다.