在国际象棋棋盘上放置国王的方法数量

时间:2012-07-08 09:47:50

标签: algorithm

你有一个N x N棋盘,你希望在它上面放置N个国王。每一行和每列应该只包含一个国王,并且没有两个国王应该相互攻击(如果两个国王存在于共享角落的方格中,则两个国王相互攻击)。

董事会的前K行中的国王已经被放置。你被赋予这些国王的位置作为数组pos []。 pos [i]是第i行中的国王已被放置的列。所有指数均为0指数。剩下的国王可以有多少种方式摆放?

Input:
The first line contains the number of test cases T. T test cases follow. Each test case contains N and K on the first line, followed by a line having K integers, denoting the array pos[ ] as described above.

Output:
Output the number of ways to place kings in the remaining rows satisfying the above conditions. Output all numbers modulo 1000000007.

Constraints:
1 <= T <= 20
1 <= N <= 16
0 <= K <= N
0 <= pos_i < N
The kings specified in the input will be in different columns and not attack each other.

Sample Input:
5
4 1
2
3 0

5 2
1 3
4 4
1 3 0 2
6 1
2

Sample Output:
1
0
2
1
18

说明: 对于第一个例子,有一个国王已经放在第0行和第2列。第二行中的国王必须属于第0列。第三行中的国王必须属于第3列,最后一个国王必须属于第3列因此,只有一个有效的位置。

对于第二个示例,没有有效的展示位置。

我应该如何处理这个问题

4 个答案:

答案 0 :(得分:3)

回溯可能太慢了。考虑到某一行k中的解的数量仅取决于行k-1中的王的位置和行

答案 1 :(得分:2)

你应该使用回溯来解决这个问题,如下所示的简单函数可以解决你的问题,(处理输入文件和输出很容易,所以我跳过它)。

int CanPlaceKingInPosition(int pos[],int MaxIndex,int NewCol){
    for(int i=0;i<MaxIndex-1;i++)
        if(pos[i]==NewCol)
            return 0;
    //MaxIndex is the index of the above row of the new king, so we have to check attacking conditions

    if (abs(pos[MaxIndex-1]-NewCol)<=1)
       return 0;
    return 1;
}

int solver(int pos[], int N, int K){      
    int result=0;
    if (K>N) //termination condition
        return result;
    if (K==N-1) //last row
        return IsOnlyPossibleColAGoodOne(pos,N,N-1);
    for (int i=0;i<N;i++){ //for each column if we can place the king in it, move one step forward
        if (CanPlaceKingInPosion(pos,K,i)){
            pos[K]=i;  //add new king
            result+=solver(pos,N,K+1);  
        }
    }
    return result;
}

你可以从main()调用这个函数,如下所示: //read N,K //fill pos

printf("%d",solver(pos,N,K+1) % 1000000007)

“IsOnlyPossibleColAGoodOne”函数返回1,如果可以将一个王放在船上留下的唯一空闲列中(这样做很简单)。 我没有测试过这个函数,所以你应该把它看作一个指导而不是实际代码。(它可能工作正常,但我没有测试过它)

P.S:这是一个ACM / ICPC问题吗?

答案 2 :(得分:0)

Hello使用下面的代码我可以产生有效的王位置的排列,如果内存不是约束,我们可以生成高达16X16的所有排列并将它们存储在相应的表中 对于给定的测试用例生成相应的不完全排列,可以匹配已经生成的相应NXN板的排列,计算将是多么多的答案

int columns[]={1,2,3,4,5,6,7,8,9,10,11,12};

public void displayPermitationsBoth(int prev,StringBuilder sb,int n,int stage){
    if(stage==n){
        display(sb);
        return;
    }
    String localStr=sb.toString();
    int localStage=stage;
    for(int i=0;i<n;i++){
        if((sb.toString().contains("-"+Integer.toString(columns[i])+"-"))||(Math.abs(prev-columns[i])==1)){
            continue;
        }
        displayPermitationsBoth(columns[i],sb.append("-"+columns[i]+"-"),n,++stage);
        stage=localStage;
        sb.delete(0,sb.capacity());
        sb.append(localStr);
    }
}

答案 3 :(得分:0)

import java.util.*;

/**
*
* @author BENDIABDELLAH
**/
public class Solution {

boolean boards[][];
Set<Integer> occupied_CL = new HashSet<Integer>();

Solution(int n) {
    boards = new boolean[n][n];
}

Solution() {
}

void setBoard(boolean[][] boards) {
    this.boards = boards;
    for (int i = 0; i < boards.length; ++i) {
        for (int j = 0; j < boards.length; ++j) {
            if (boards[i][j]) {
                occupied_CL.add(j);
            }
        }
    }
}

int waysToPlace(int k) {
    if (k == boards.length - 1) {
        return 1;
    }
    int totalWays = 0;
    for (int pos = 0; pos < boards.length; ++pos) {
        int ways = 1;
        if (!isAttack(k + 1, pos)) {
            boards[k + 1][pos] = true;
            occupied_CL.add(pos);
            ways *= waysToPlace(k + 1);
            boards[k + 1][pos] = false;
            occupied_CL.remove(pos);
        } else {
            ways = 0;
        }
        totalWays += ways;
    }
    return totalWays;
}

boolean isAttack(int row, int col) {
    if (occupied_CL.contains(col)) {
        return true;
   }
    if ((col > 0 && row > 0 && boards[row - 1][col - 1]) || (col < boards.length - 1 && row > 0 && boards[row - 1][col + 1])) {
        return true;
    }
    return false;
}

void printArray() {
    for (int i = 0; i < boards.length; ++i) {
        for (int j = 0; j < boards.length; ++j) {
            System.out.print(boards[i][j] + " ");
        }
        System.out.println();
    }
}

public static void main(String args[]) {
    //Solution sol = new Solution(5);
    // System.out.println(sol.waysToPlace(-1));
    //sol.printArray();
    readInput();
}

static void readInput() {
    Scanner scan = new Scanner(System.in);
    int t = scan.nextInt();
    for (int i = 0; i < t; ++i) {
        int n = scan.nextInt();
        //System.out.println(" n "+n );
        int k = scan.nextInt();
        // System.out.println(" k "+k );
        boolean boards[][] = new boolean[n][n];
        for (int row = 0; row < k; ++row) {
            int col = scan.nextInt();
            boards[row][col] = true;
        }
        Solution s = new Solution();
        s.setBoard(boards);
        int ways = s.waysToPlace(k - 1);
        System.out.println(ways);
        }
    }
}