프로그램은 가능한 모든 순열을 생성 한 다음 순열이 유효한지 테스트합니다. 테스트 자체에는 중첩 루프가 포함됩니다. Photon이 제안한 것처럼 검사가보다 효율적이거나 검색 공간에서 막 다른 곳을 찾을 수 있도록 데이터 구조를 최적화 할 수 있습니다.
보다 효율적인 방법은 올바른 순열 만 만들어 지도록 프로그램을 설계하는 것입니다. 이렇게하면 검색 공간이 줄어들고 테스트가 제거됩니다.
5
|
1 6
| |
0---2---7
| |
3 8
|
4
당신이 도구 0에서 시작하여 슬롯 0에 넣어 경우, 다음 단계는을 배치하는 것입니다 :
당신이 문제를 설명의 예를 보면은 wrie 네트워크는 비순환 그래프이다 툴 1과 툴 3, 그리고 각각의 연결된 도구 들인 툴 2와 그 "자손들"의 순열. 도구 0의 관점에서이를 다음과 같이 트리로 바꿀 수 있습니다.
[1237]
// | \
1 2 [34] [678]
/| | \ \
3 4 [56] 7 8
| \
5 6
여기에서 잎은 하나의 도구에 해당합니다. 가지에는 여러 가지 도구가 있습니다. 가지의 모든 prumutations 유효한 배열을 형성합니다. 물론
0 (1 2 (3 4) ((5 6) 7 8))
는 [56]
의 모든 순열은 다른 지점의 모든 순열과 조합해야합니다.각 공간에서 0에서 9까지의 숫자를 거치지 않고 지점의 가능한 순열을 통해 일종의 주행 거리계를 구현하면됩니다.
모든 생성 된 순열이 유효하지만,이 기술은 모든 가능한 순열을 아직 생성하지 않습니다. 슬롯 0에 공구 0을 고정 시켰지만 그럴 필요는 없다는 것을 기억하십시오. 그러나 유효한 레이아웃의 지형은 그것을 회전시키고 슬롯 0에 도구 0을 넣는 등 8 개의 다른 레이아웃을 생성하는 데 사용할 수 있습니다.
이 기술을 사용하면 검색 공간이 9에서 줄어 듭니다. ~ 9 & middot; 4! & middot; 2! & middot; 삼! & middot; 2! 또는 70의 인자로 나타낼 수 있습니다. 테스트는 없지만보다 복잡한 데이터 구조를 사용합니다.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
enum {
N = 16 // hardcoded max. size
};
struct tool {
int conn[N - 1]; // wire connections
int nconn;
int desc[N]; // "descendants" of the tree node
int ndesc;
int cost[N]; // row of the cost matrix
int used; // flag for recursive descent
};
struct drill {
int n;
struct tool tool[N];
int root; // root node
int branch[N]; // indices of branch nodes
int nbranch; // permutating branches
int opt; // current optimum
};
void swap(int a[], int i, int j)
{
int s = a[i]; a[i] = a[j]; a[j] = s;
}
void reverse(int a[], int i, int n)
{
while (i < --n) swap(a, i++, n);
}
/*
* Turn an array to the next higher permutation. When the
* permutation is already the highest, return 0 and reset the
* array to the smalles permutation. Otherwise, return 1.
*/
int next_perm(int a[], int n)
{
int i = n - 1;
int k = n - 1;
if (n < 2) return 0;
while (k && a[k] < a[k - 1]) k--;
if (k == 0) {
reverse(a, 0, n);
return 0;
}
k--;
while (i > k && a[i] < a[k]) i--;
swap(a, i, k);
reverse(a, k + 1, n);
return 1;
}
/*
* Insertion sort for sorting the branches at the beginning.
*/
void sort(int a[], int len)
{
for (int i = 1; i < len; i++) {
int k = i;
while (k > 0 && a[k] < a[k - 1]) {
swap(a, k, k - 1);
k--;
}
}
}
/*
* Determine the list of descendants for each node.
*/
void descend(struct drill *dr, int n)
{
struct tool *t = dr->tool + n;
t->ndesc = 1;
t->desc[0] = n;
t->used = 1;
for (int i = 0; i < t->nconn; i++) {
int m = t->conn[i];
if (dr->tool[m].used == 0) {
t->desc[t->ndesc++] = m;
descend(dr, m);
}
}
if (t->ndesc > 1) {
sort(t->desc, t->ndesc);
dr->branch[dr->nbranch++] = n;
}
t->used = 0;
}
/*
* Fill the array a with the current arrangement in the tree.
*/
int evaluate(struct drill *dr, int a[], int n)
{
struct tool *t = dr->tool + n;
int m = 0;
if (n == dr->root) {
a[0] = dr->root;
return 1 + evaluate(dr, a + 1, dr->tool[n].conn[0]);
}
for (int i = 0; i < t->ndesc; i++) {
int d = t->desc[i];
if (d == n) {
a[m++] = d;
} else {
m += evaluate(dr, a + m, d);
}
}
return m;
}
/*
* Evaluate all possible permutations and find the optimum.
*/
void optimize(struct drill *dr)
{
dr->opt = (1u << 31) - 1;
for (;;) {
int i = 0;
struct tool *t = dr->tool + dr->branch[0];
for (int j = 0; j < dr->n; j++) {
int a[2 * N];
int cost = 0;
evaluate(dr, a, dr->root);
for (int i = 0; i < dr->n; i++) {
int k = (i + j) % dr->n;
cost += dr->tool[i].cost[a[k]];
}
if (cost < dr->opt) dr->opt = cost;
}
while (next_perm(t->desc, t->ndesc) == 0) {
i++;
if (i == dr->nbranch) return;
t = dr->tool + dr->branch[i];
}
}
}
/*
* Read and prepare drill data, then optimize.
*/
int main(void)
{
struct drill dr = {0};
fscanf(stdin, "%d", &dr.n);
for (int j = 0; j < dr.n; j++) {
for (int i = 0; i < dr.n; i++) {
scanf("%d", &dr.tool[j].cost[i]);
}
}
for (int i = 1; i < dr.n; i++) {
int a, b;
scanf("%d", &a);
scanf("%d", &b);
dr.tool[a].conn[dr.tool[a].nconn++] = b;
dr.tool[b].conn[dr.tool[b].nconn++] = a;
}
while (dr.tool[dr.root].nconn > 1) dr.root++;
dr.tool[dr.root].used = 1;
descend(&dr, dr.tool[dr.root].conn[0]);
optimize(&dr);
printf("%d\n", dr.opt);
return 0;
}
설명해주십시오 :
이 코드는 설명 된 기술을 구현합니다. (감소는 전선의 네트워크 IR 분기점없이 정말 그냥 직선이 12 도구의 예에 극단적이다) 텍스트 문제가 아니라 이미지와 (링크를 통해). – wildplasser
모두 12 개를 만듭니다! 순열은 이미 많이 있습니다. 그런 다음 각 순열에 대한 설정이 처음부터 가능한지 테스트합니다. 처음부터 유효한 순열만을 방문하도록하여 평가 횟수를 줄이고 테스트를 저장하도록 알고리즘을 설계해야합니다. –