Light OJ 1061 - N Queen Again(搜索+状压DP)

12 篇文章 0 订阅

大致题意:

8*8的棋盘,已知八个皇后的位置,问最少移动多少次,可以让八个皇后不互相攻击。(同行,同列,同斜线视为互相攻击)

思路:

易知八皇后不攻击一共有92种,dfs出这92种,然后对于每种状压求出最少需要移动多少次

复杂度: O( 92 * n * 2 ^ n) (n = 8)


//package ok;
import java.math.*;
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.math.BigInteger;  
import java.util.StringTokenizer;  
import java.io.PrintWriter;
import java.util.Arrays;
public class Main {
	static char mp[][] = new char[10][10];
	static pair poi[] = new pair[10];
	static int top = 0;
	static int path[] = new int[10];
	static int dp[] = new int[1 << 8];
	static boolean use[] = new boolean[22];
	static boolean vis[] = new boolean[123];
	static int ans = 0;
	public static void main(String args[])	{
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int T = in.nextInt();
		for(int cas = 1; cas <= T; cas ++) {
			ans = 1 << 25;
			top = 0;
			in.nextLine();
			for(int i = 0; i < 8;i ++) 
				mp[i] = in.nextLine().toCharArray();
	
			for(int i = 0; i < 8; i ++){
				for(int j = 0; j < 8; j ++) 
					if(mp[i][j] == 'q') poi[++top] = new pair(i + 1, j + 1);
			}
			dfs(1);
			out.printf("Case %d: %d\n", cas, ans);
			out.flush();
		}
	}
	static int cal(pair p, int id) {
		if(p.X == id && p.Y == path[id] ) return 0;
		if(p.X == id || p.Y == path[id] || p.X + p.Y == id + path[id] || p.X - p.Y == id - path[id] ) return 1;
	  	return 2;	
	}
	static void dfs(int x) {
		if( x == 9 ) {
			dp[0] = 0;
			for(int mask = 1; mask < (1 << 8); mask++) {
				dp[mask] = 1 << 25;
				int c = 0;
				for(int i = 0; i < 8; i ++) 
					if((mask & (1 << i)) != 0) c ++;
				for(int k = 0; k < 8; k ++) {
					if((mask & (1 << k)) != 0) 
						dp[mask] = Math.min(dp[mask], cal(poi[c], k + 1) + dp[mask ^ (1 << k)]); 
				}
			}
			ans = Math.min(ans, dp[(1 << 8) - 1]);
			return ;
		}
		for(int y = 1; y <= 8; y ++) {
			if(!use[y] && !vis[x + y] && !vis[x -y + 50]) {
				use[y] = true;
				vis[x + y] = true;
				vis[x - y + 50] = true;
				path[x] = y;
				dfs(x + 1);
				vis[x + y] = false;
				vis[x - y + 50] = false;
				use[y] = false;
			}
		}
	}
	public static class pair{
		public int X = 0, Y = 0;
		pair(int X,int Y){
			this.X = X;
			this.Y = Y;
		}
	}

	static class Scanner {  
	    BufferedReader br;  
	    StringTokenizer st;  
	  
	    public Scanner(InputStream in) {  
	        br = new BufferedReader(new InputStreamReader(in));  
	        eat("");  
	    }  
	  
	    private void eat(String s) {  
	        st = new StringTokenizer(s);  
	    }  
	  
	    public String nextLine() {  
	        try {  
	            return br.readLine();  
	        } catch (IOException e) {  
	            return null;  
	        }  
	    }  
	  
	    public boolean hasNext() {  
	        while (!st.hasMoreTokens()) {  
	            String s = nextLine();  
	            if (s == null)  
	                return false;  
	            eat(s);  
	        }  
	        return true;  
	    }  
	  
	    public String next() {  
	        hasNext();  
	        return st.nextToken();  
	    }  
	  
	    public int nextInt() {  
	        return Integer.parseInt(next());  
	    }  
	  
	    public long nextLong() {  
	        return Long.parseLong(next());  
	    }  
	  
	    public double nextDouble() {  
	        return Double.parseDouble(next());  
	    }  
	  
	    public BigInteger nextBigInteger() {  
	        return new BigInteger(next());  
	    }  
	  
	    public int[] nextIntArray(int n) {  
	        int[] is = new int[n];  
	        for (int i = 0; i < n; i++) {  
	            is[i] = nextInt();  
	        }  
	        return is;  
	    }  
	  
	    public long[] nextLongArray(int n) {  
	        long[] ls = new long[n];  
	        for (int i = 0; i < n; i++) {  
	            ls[i] = nextLong();  
	        }  
	        return ls;  
	    }  
	 
	    public double[] nextDoubleArray(int n) {  
	        double[] ds = new double[n];  
	        for (int i = 0; i < n; i++) {  
	            ds[i] = nextDouble();  
	        }  
	        return ds;  
	    }  
	  
	    public BigInteger[] nextBigIntegerArray(int n) {  
	        BigInteger[] bs = new BigInteger[n];  
	        for (int i = 0; i < n; i++) {  
	            bs[i] = nextBigInteger();  
	        }  
	        return bs;  
	    }  
	  
	    public int[][] nextIntMatrix(int row, int col) {  
	        int[][] mat = new int[row][];  
	        for (int i = 0; i < row; i++) {  
	            mat[i] = nextIntArray(col);  
	        }  
	        return mat;  
	    }  
	  
	    public long[][] nextLongMatrix(int row, int col) {  
	        long[][] mat = new long[row][];  
	        for (int i = 0; i < row; i++) {  
	            mat[i] = nextLongArray(col);  
	        }  
	        return mat;  
	    }  
	  
	    public double[][] nextDoubleMatrix(int row, int col) {  
	        double[][] mat = new double[row][];  
	        for (int i = 0; i < row; i++) {  
	            mat[i] = nextDoubleArray(col);  
	        }  
	        return mat;  
	    }  
	  
	    public BigInteger[][] nextBigIntegerMatrix(int row, int col) {  
	        BigInteger[][] mat = new BigInteger[row][];  
	        for (int i = 0; i < row; i++) {  
	            mat[i] = nextBigIntegerArray(col);  
	        }  
	        return mat;  
	    }  
	}  
}  


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值