2013-04-19 17:41:03Morris

[UVA][數學、N皇后單一快速解] 10094 - Place the Guards

Problem J
Place the Guards

Input: Standard Input

Output: Standard Output

 

 

The king of Amazing Land has a secret place where he keeps his treasure. No one knows what is the size of that place. Some say that it is (4 * 4) and some others say that it is (1000 * 1000). The rooms in this secret place are also square shaped and of unit length and width.  So a (4 * 4) place has 16 rooms as shown in the pictures below. So a (n * n) place has n^2 or (n * n) rooms. n guards are used to look after the (n * n) sized secret place. In the picture below each second largest square denotes a room. The gray square inside each room indicates free space where the guards stand. The outgoing tunnels (dark gray in color) from the free space denote the tunnels to go into and out of the rooms. As you can see that the tunnels are designed in such a way that only the guards on the same row, same column and same diagonal can see each other. If we use (row, column) denoting scheme we can say that in figure 1 guard (2, 1) can see guard (3, 2) and guard (3,2) can see guard (4, 3). Although guard (2,1) and guard (4, 3) are in the same diagonal they cannot see each other as guard (3, 2) stands between them. For obvious reasons guard (2, 1) can see guard (2, 4) but guard (3, 2) cannot see guard (2, 4). The King always places his guards in such a way that no guard can see any other guard. In the empty rooms (where there is no guard) he keeps his treasure. The King arranges his guards in this way because he thinks when a guard sees another guard they start gossiping and thus lose concentration. You are to help the King to place his guards.

 


    Fig 1:  Invalid Guard Layout                                                Fig 2: Valid Guard Layout            

 

Input

Input File will contain an integer in each line, which indicates the value of n (The length or width of one side of the secret place). Remember that (1<n<1001). Input is terminated by End of File.


Output

As it is obvious that only one guard can be placed in each column. For each input value of n you will have to print a line of n integers. The integers will be separated by a single space. These integers denote the row positions of guards in each column. For the valid configuration of guards in figure 2 you will print the line 2 4 1 3 as in column 1 the guard is placed on row 2, in column 2 the guard is placed on row 4 and so on. There can be multiple solutions. Any good solution will be accepted. If guards cannot be placed in the secret place print the line “Impossible” in a single line.

                                             

                 

Sample Input

4
8
10

Sample Output

2 4 1 3
4 6 8 2 7 1 3 5
2 4 6 8 10 1 3 5 7 9

__________________________________________________________________________________________
Shahriar Manzoor


數學解如下,轉自網路

一、当n mod 6 != 2 且 n mod 6 != 3时,有一个解为:

2,4,6,8,...,n,1,3,5,7,...,n-1       (n为偶数)

2,4,6,8,...,n-1,1,3,5,7,...,n       (n为奇数)

(上面序列第i个数为ai,表示在第i行ai列放一个皇后;... 省略的序列中,相邻两数以2递增。下同)


二、当n mod 6 == 2 或 n mod 6 == 3时,

(当n为偶数,k=n/2;当n为奇数,k=(n-1)/2)

k,k+2,k+4,...,n,2,4,...,k-2,k+3,k+5,...,n-1,1,3,5,...,k+1         (k为偶数,n为偶数)

k,k+2,k+4,...,n-1,2,4,...,k-2,k+3,k+5,...,n-2,1,3,5,...,k+1,n       (k为偶数,n为奇数)

k,k+2,k+4,...,n-1,1,3,5,...,k-2,k+3,...,n,2,4,...,k+1               (k为奇数,n为偶数)

k,k+2,k+4,...,n-2,1,3,5,...,k-2,k+3,...,n-1,2,4,...,k+1,n           (k为奇数,n为奇数)


#include <stdio.h>

int main() {
    int n, k, i;
    while(scanf("%d", &n) == 1) {
        if(n <= 3) {
            puts("Impossible");
            continue;
        }
        if(n%6 != 2 && n%6 != 3) {
            printf("2");
            for(i = 4; i <= n; i += 2)
                printf(" %d", i);
            for(i = 1; i <= n; i += 2)
                printf(" %d", i);
        } else {
            if(n&1) k = (n-1)/2;
            else    k = n/2;
            if(k%2 == 0 && n%2 == 0) {
                printf("%d", k);
                for(i = k+2; i <= n; i += 2)
                    printf(" %d", i);
                for(i = 2; i <= k-2; i += 2)
                    printf(" %d", i);
                for(i = k+3; i <= n-1; i += 2)
                    printf(" %d", i);
                for(i = 1; i <= k+1; i += 2)
                    printf(" %d", i);
            }
            if(k%2 == 0 && n%2 == 1) {
                printf("%d", k);
                for(i = k+2; i <= n-1; i += 2)
                    printf(" %d", i);
                for(i = 2; i <= k-2; i += 2)
                    printf(" %d", i);
                for(i = k+3; i <= n-2; i += 2)
                    printf(" %d", i);
                for(i = 1; i <= k+1; i += 2)
                    printf(" %d", i);
                printf(" %d", n);
            }
            if(k%2 == 1 && n%2 == 0) {
                printf("%d", k);
                for(i = k+2; i <= n-1; i += 2)
                    printf(" %d", i);
                for(i = 1; i <= k-2; i += 2)
                    printf(" %d", i);
                for(i = k+3; i <= n; i += 2)
                    printf(" %d", i);
                for(i = 2; i <= k+1; i += 2)
                    printf(" %d", i);
            }
            if(k%2 == 1 && n%2 == 1) {
                printf("%d", k);
                for(i = k+2; i <= n-2; i += 2)
                    printf(" %d", i);
                for(i = 1; i <= k-2; i += 2)
                    printf(" %d", i);
                for(i = k+3; i <= n-1; i += 2)
                    printf(" %d", i);
                for(i = 2; i <= k+1; i += 2)
                    printf(" %d", i);
                printf(" %d", n);
            }
        }
        puts("");
    }
    return 0;
}


隨機化方法:但是不會調好的隨機
原本想打表的,上傳卻發現
Code length can't be over 40 kilobytes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int P[1005], n;
void step1() {
    int i, j, k;
    for(i = 1; i <= n; i++)
        P[i] = i;
    for(i = 1; i <= 65536; i++) {
        j = rand()%n+1;
        k = rand()%n+1;
        swap(P[j], P[k]);
    }
}// random init solution for n-queen
int column[1005];
int markRight[2005], markLeft[2005];
int error;
int injure[2005], inSize, chNode, chColumn;
int mnAttack[2005], mnSize;
int mn;
void step2a() {
    int i, x, y, right, left;
    inSize = 0;
    for(i = 1; i <= n; i++) {
        x = i, y = P[i];
        if(x >= y)  right = x-y;
        else        right = y-x+n;
        x = i, y = n-P[i]+1;
        if(x >= y)  left = x-y;
        else        left = y-x+n;
        if(column[P[i]] > 1 || markRight[right] > 1 || markLeft[left] > 1) {
            injure[inSize++] = i;
        }
    }
    if(inSize == 0) {
        printf("%d XXX\n", error);
    }
    chNode = injure[rand()%inSize];
    //printf("injure %d\n", inSize);
    x = chNode, y = P[chNode];
    if(x >= y)  right = x-y;
    else        right = y-x+n;
    x = chNode, y = n-P[chNode]+1;
    if(x >= y)  left = x-y;
    else        left = y-x+n;
    if(column[P[chNode]] == 2)  error--;
    if(markRight[right] == 2)   error--;
    if(markLeft[left] == 2)     error--;
    column[P[chNode]]--, markRight[right]--, markLeft[left]--;
    mn = column[P[chNode]]+markRight[right]+markLeft[left];
}
void step2b() {
    int i, x, y, right, left, tmp;
    mnSize = 0;
    for(i = 1; i <= n; i++) {
        x = chNode, y = i;
        if(x >= y)  right = x-y;
        else        right = y-x+n;
        x = chNode, y = n-i+1;
        if(x >= y)  left = x-y;
        else        left = y-x+n;
        tmp = column[i] + markRight[right] + markLeft[left];
        //printf("i %d : %d %d queen\n", i, tmp, mn);
        if(tmp <= mn)
            mnAttack[mnSize++] = i;
    }
    /*printf("set :");
    for(i = 0; i < mnSize; i++)
        printf(" %d", mnAttack[i]);
    puts("");*/
    if(mnSize == 0) {
        for(i = 1; i <= n; i++) {
            x = chNode, y = i;
            if(x >= y)  right = x-y;
            else        right = y-x+n;
            x = chNode, y = n-i+1;
            if(x >= y)  left = x-y;
            else        left = y-x+n;
            tmp = column[i] + markRight[right] + markLeft[left];
            //printf("i %d : %d %d queen\n", i, tmp, mn);
            if(tmp == mn)
                mnAttack[mnSize++] = i;
        }
    }
    chColumn = mnAttack[rand()%mnSize];
    P[chNode] = chColumn;
    x = chNode, y = P[chNode];
    if(x >= y)  right = x-y;
    else        right = y-x+n;
    x = chNode, y = n-P[chNode]+1;
    if(x >= y)  left = x-y;
    else        left = y-x+n;
    if(column[P[chNode]] == 1)  error++;
    if(markRight[right] == 1)   error++;
    if(markLeft[left] == 1)     error++;
    column[P[chNode]]++, markRight[right]++, markLeft[left]++;
}
int step2() {
    error = 0;
    memset(column, 0, sizeof(column));
    memset(markRight, 0, sizeof(markRight));
    memset(markLeft, 0, sizeof(markLeft));
    int i, x, y, right, left;
    for(i = 1; i <= n; i++) {
        x = i, y = P[i];
        if(x >= y)  right = x-y;
        else        right = y-x+n;
        x = i, y = n-P[i]+1;
        if(x >= y)  left = x-y;
        else        left = y-x+n;
        markRight[right]++;
        markLeft[left]++;
        column[y]++;
    }
    for(i = 0; i < 2*n; i++) {
        if(markRight[i] > 1)
            error++;
        if(markLeft[i] > 1)
            error++;
    }
    int times = 0;
    while(error) {
        times++;
        /*printf("%d", P[1]);
        for(i = 2; i <= n; i++)
            printf(" %d", P[i]);
        puts("");*/
        step2a();
        step2b();
        /*printf("%d", P[1]);
        for(i = 2; i <= n; i++)
            printf(" %d", P[i]);
        puts("");*/
        /*printf("chNode %d column %d\n", chNode, chColumn);
        printf("error %d\n", error);*/
    //    getchar();
        /*if(times > 300) {
            puts("unluck");
            break;
        }*/
    }
    //printf("%d\n", times);
    return 1;
}
int main() {
    srand(514);
    int i;
    puts("char ans[1005][5005] = {{""},{""}");
    while(scanf("%d", &n) == 1) {
        if(n <= 3) {
            puts(",{\"Impossible\"}");
            continue;
        }
        step1();
        step2();
        srand(rand());
        printf(",{\"");
        printf("%d", P[1]);
        for(i = 2; i <= n; i++)
            printf(" %d", P[i]);
        puts("\"}");
    }
    puts("};");
    return 0;
}

連 DLX+Random 都來湊一腳了,
心灰意冷了,速度不夠快。


#include <stdio.h>
#include <algorithm>
using namespace std;
struct DancingLinks {
    int left, right, up, down, ch;
    int rh; // 額外的 data
} DL[4000000 + 10001];
int s[10001], o[10001], head, size;
int n; // this problem need n for output process.
void remove(int c) {
    DL[DL[c].right].left = DL[c].left;
    DL[DL[c].left].right = DL[c].right;
    int i, j;
    for(i = DL[c].down; i != c; i = DL[i].down) {
        for(j = DL[i].right; j != i; j = DL[j].right) {
            DL[DL[j].down].up = DL[j].up;
            DL[DL[j].up].down = DL[j].down;
            s[DL[j].ch]--;
        }
    }
}
void resume(int c) {
    int i, j;
    for(i = DL[c].down; i != c; i = DL[i].down) {
        for(j = DL[i].left; j != i; j = DL[j].left) {
            DL[DL[j].down].up = j;
            DL[DL[j].up].down = j;
            s[DL[j].ch]++;
        }
    }
    DL[DL[c].right].left = c;
    DL[DL[c].left].right = c;
}
int found;
void print() {
    int i;
    int ans[1000];
    for(i = 0; i < n; i++) {
        ans[DL[o[i]].rh/n] = DL[o[i]].rh%n;
        //printf("(%d, %d)", DL[o[i]].rh/n+1, DL[o[i]].rh%n+1);
    }
    //puts("");
    printf("%d", ans[0]+1);
    for(i = 1; i < n; i++)
        printf(" %d", ans[i]+1);
    puts("");
}
void dfs(int dep) {
    if(found)   return;
    if(dep == n) { // just match for row&column
        found = 1;
        print();
        return;
    }
    int tmp = 0xffff, c, i, j;
    for(i = DL[head].right; i != head; i = DL[i].right) {
        if(i > 2*n)
            break;
        if(s[i] <= tmp)
            tmp = s[i], c = i;
    }
    remove(c);
    for(i = DL[c].down; i != c; i = DL[i].down) {
        o[dep] = i;
        for(j = DL[i].right; j != i; j = DL[j].right)
            remove(DL[j].ch);
        dfs(dep+1);
        if(found)   return;
        for(j = DL[i].left; j != i; j = DL[j].left)
            resume(DL[j].ch);
    }
    resume(c);
}
int getnode(int u, int d, int l, int r) {
    DL[size].up = u, DL[size].down = d;
    DL[size].left = l, DL[size].right = r;
    DL[u].down = DL[d].up = DL[l].right = DL[r].left = size;
    return size++;
}
void newrow(int r[], int rn, int rh) {
    int i, j, h;
    for(i = 0; i < rn; i++) {
        DL[size].ch = r[i], s[r[i]]++;
        DL[size].rh = rh; // 額外的 data
        if(i) {
            j = getnode(DL[DL[r[i]].ch].up, DL[r[i]].ch, DL[h].left, h);
        } else {
            h = getnode(DL[DL[r[i]].ch].up, DL[r[i]].ch, size, size);
        }
    }
}
void init(int c) {// total column
    size = 0;
    head = getnode(0,0,0,0);
    int i;
    for(i = 1; i <= c; i++) {
        getnode(i, i, DL[head].left, head);
        DL[i].ch = i, s[i] = 0;
    }
}
int main() {
    int i, j, k;
    int P[2005];
    srand(514);
    while(scanf("%d", &n) == 1) {
        found = 0;
        int column = n+n+2*(2*n-1); //row + cloumn + two diagonal
        init(column);
        int row[10], rn;
        srand(rand());
        for(i = 1; i <= 2*n; i++)
            P[i] = i;
        int times = rand()%5140+5140;
        for(i = 1; i <= times; i++) {
            j = rand()%(2*n)+1;
            k = rand()%(2*n)+1;
            swap(P[j], P[k]);
        }
        for(i = 1; i <= n; i++) {
            for(j = 1; j <= n; j++) {
                rn = 0;
                //row[rn++] = i;     // row
                //row[rn++] = n+j;   // column
                row[rn++] = P[i];
                row[rn++] = P[n+j];
                if(i >= j) {
                    row[rn++] = i-j+1+(2*n);//left diagonal
                } else {
                    row[rn++] = j-i+n+(2*n);//left diagonal
                }
                int tx = i, ty = n-j+1;
                if(tx >= ty) {
                    row[rn++] = tx-ty+1+(2*n+2*n-1);//right diagonal
                } else {
                    row[rn++] = ty-tx+n+(2*n+2*n-1);//right diagonal
                }
                //printf("(%d %d) %d %d %d %d\n", i, j, row[0], row[1], row[2], row[3]);
                newrow(row, rn, (i-1)*n+j-1);
            }
        }
        dfs(0);
        if(!found)
            puts("Impossible");
    }
    return 0;
}