`
qingtangpaomian
  • 浏览: 37818 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

USACO - 1.5.4 - Checker Challenge

 
阅读更多

原创文章转载请注明出处


摘要:枚举,棋盘翻转,位运算 , 三星

一. 题目翻译

1. 描述:
检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下: 行号 1 2 3 4 5 6 列号 2 4 6 1 3 5 这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

2. 格式:

          INPUT FORMAT:

          (checker.in)
          一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。

          OUTPUT FORMAT:

          (checker.out)
          前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

3. SAMPLE:
          SAMPLE INPUT:
 6
          SAMPLE OUTPUT:
2 4 6 1 3 5 
3 6 2 5 1 4 
4 1 5 2 6 3 
4

          
二.  题解

1. 题意理解(将问题分析清楚,大致用什么思路):
          这道题目最基本的思路就是枚举,枚举所有可能出现的组合。
          这里有三个限制的条件,也就是题目中的列限制、正对角线限制、反对角线限制。我们使用三个数组来表示,数组中元素为1表示当前的这个节点不可用。
          但是即使是这样枚举,题目也很有可能超时。可以按照题目当中的hint做一个简单的优化:如果棋盘的大小N是偶数,则第一行只需要枚举前N/2列,这样没搜索出一种情况以后,沿中线翻转就可以产生另一个解(由于只枚举前N/2列所以不会重复)
          要特别注意的是,这种算法在计算题目解的个数时可以减少复杂度。但是在N=6时,枚举第一行的前3列仅能产生2个解,所以需要对N=6的情况要进行单独的枚举。

 

2. 具体实现(具体实现过程中出现的问题):
          参考代码注释。

3. 需要注意的细节:

        棋盘大小N等于6的情况要单独考虑。

4. 启示:

        翻转棋盘求解非常有意思,大家还可以思考更好的优化方法。
        这道题目还有大神使用位运算,大家可以了解一下位运算。



三.  代码

/*
ID:fightin1
LANG:JAVA
TASK:checker
*/

//package session_1_5_4;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Scanner;

public class checker {

	static int length;
	static int[] result;
	static int size;
	static int[] columnInUse;
	static int[] diagonalInUse1;
	static int[] diagonalInUse2;
	static PrintWriter pw;
	
	public static void main(String[] args) {
		try {
//			Scanner in = new Scanner(System.in);
//			pw = new PrintWriter(System.out);
			
			Scanner in = new Scanner(new BufferedReader(new FileReader(
			"checker.in")));
			pw = new PrintWriter(new BufferedWriter(new FileWriter(
			"checker.out")));
			
			length = in.nextInt();
			size = 0;
			result = new int[length + 1];
			columnInUse = new int[length + 1];
			diagonalInUse1 = new int[2 * length + 1]; // "\" in use
			diagonalInUse2 = new int[2 * length + 1]; // "/" in use
			
			if (length == 6){
				placeInRow(0);
				
			} else {
				if (length%2 == 0){
					placeInRow(1);
					size = 2*size;
				} else {
					placeInRow(1);
					size = 2*size;
					columnInUse[length/2+1] = 1;
					diagonalInUse1[length/2 + length] = 1;
					diagonalInUse2[length/2 + 2] = 1;
					placeInRow(2);
				
				}
			}
			pw.println(size);
			pw.close();
			in.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void placeInRow(int row){
		if (row == length+1){
			size ++ ;
			if (size<=3){
				pw.print(result[1]);
				for (int i=2;i<=length;i++){
					pw.print(" "+result[i]);
				}
				pw.println();
			} 
		} else {
			int bound = length;
			if (row == 0){
				row = 1;
			} else if (row == 1){
				bound = length/2;
			}
			for (int col = 1; col <= bound; col++){
				int diagonal1 = col - row + length;
				int diagonal2 =  col + row ;
				if(columnInUse[col]==0&&diagonalInUse1[diagonal1]==0&&diagonalInUse2[diagonal2]==0){
					columnInUse[col] = 1;
					diagonalInUse1[diagonal1] = 1;
					diagonalInUse2[diagonal2] = 1;
					result[row] = col;
					placeInRow(row+1);
					columnInUse[col] = 0;
					diagonalInUse1[diagonal1] = 0;
					diagonalInUse2[diagonal2] = 0;
					result[row] = col;
				}
			}
		}
	}
}


 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics