[USACO]checker

八皇后问题,要求输出按数值排序的前三种布局方式(用一个数组代表每行皇后放置位置),以及布局的种类。

写了两个方案,第一个为循环,第二个为递归。循环复杂度超了一点,没有通过。递归做了优化,可以通过。

两个方案都贴出来,做些对比:

方案一:循环,用一个数组保存前几行皇后摆放情况以及未放置皇后的列信息。第二种方法也是用同样的数组进行信息保存,这样做不知道算不算是个偷巧,因为这样并不能保证得到全部的布局序列的有序,但可以保证前几项是有序的,以及可以输出全部的布局序列。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;

public class checker {
    public static void main(String[] args) throws IOException,FileNotFoundException {
	BufferedReader br = new BufferedReader(new FileReader("checker.in"));
	FileWriter fout = new FileWriter("checker.out");
	int dimension = Integer.parseInt(br.readLine());
	LinkedList<int[]> queue = new LinkedList<int[]>();
	int[] init = new int[dimension];
	for(int i = 0;i<dimension;i++) {
	    init[i]=i;
	}
	queue.add(init);
	long start = System.currentTimeMillis();
	for(int layer=0;layer<dimension;layer++) {
	    int length_queue = queue.size();
	    for(int j =0;j<length_queue;j++) {
		int[] list = queue.poll();
		 for(int i = layer;i<dimension;i++) {
		    if(isPassed(list,layer,list[i])) {
			int[] tmp =list.clone();
			swap(tmp,layer,i);
			queue.add(tmp);
		    }
		}
	    }
	}

	int size = queue.size();
	String result = new String();
	if(queue.size()>2) {
	    for(int i = 0;i<3;i++) {
		int[] tmp = queue.poll();
		for(int j = 0;j<dimension;j++){
		    result+=" "+(tmp[j]+1);
		}
		fout.write(result.substring(1)+"\n");
		result = new String();
	    }
	}
	long end= System.currentTimeMillis();
	System.out.println(end-start);
	fout.write(size+"\n");
	fout.flush();
	fout.close();
	log.flush();
	log.close();
	br.close();
	System.exit(0);
    }
    private static void swap(int[] tmp, int k, int i) {
	if(k==i) {
	    return;
	}
	int t = tmp[k];
	tmp[k] = tmp[i];
	tmp[i] = t;
    }

    private static boolean isPassed(int[] list, int layer, int value) {
	for(int i = 0;i<layer;i++) {
	    if(list[i]==value||list[i]-value==layer-i||list[i]-value==i-layer)
		return false;
	}
	return true;
    }
}

方案二:递归,复杂度O(N!)

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;

public class checker {
    private static FileWriter log ;
    private static int dimension;
    private static int counter = 0;
    public static void main(String[] args) throws IOException,FileNotFoundException {
	BufferedReader br = new BufferedReader(new FileReader("checker.in"));
//	FileWriter fout = new FileWriter("checker.out");
	log = new FileWriter("checker.out");
	dimension = Integer.parseInt(br.readLine());
	LinkedList<int[]> queue = new LinkedList<int[]>();
	int[] init = new int[dimension];
	for(int i = 0;i<dimension;i++) {
	    init[i]=i;
	}
	queue.add(init);
	long start = System.currentTimeMillis();
	queen(init,0);
	long end= System.currentTimeMillis();
	System.out.println(end-start);
	log.write(counter+"\n");
	log.flush();
	log.close();
	br.close();
	System.exit(0);
    }
    private static void queen(int[] column,int layer) {
	if(layer==dimension) {
	    if(counter<3)
		printer(column);
	    counter++;
	}
	for(int i =layer;i<dimension;i++) {
	    if(isPassed(column,layer,column[i])) {
		swap(column,layer,i);
		queen(column,layer+1);
		swap(column,layer,i);
	    }
	}
    }
    private static void printer(int[] tmp) {
	try {
	    String result = new String();
	for(int i : tmp)
	    result +=" "+(i+1);
	log.write(result.substring(1)+"\n");
	 } catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
    }

    private static void swap(int[] tmp, int k, int i) {
	if(k==i) {
	    return;
	}
	int t = tmp[k];
	tmp[k] = tmp[i];
	tmp[i] = t;
    }

    private static boolean isPassed(int[] list, int layer, int value) {
	for(int i = 0;i<layer;i++) {
	    if(list[i]==value||list[i]-value==layer-i||list[i]-value==i-layer)
		return false;
	}
	return true;
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值