2016省赛javaA组7题----剪邮票(填空)

import java.util.Scanner;

public class TestOne {

	static int ans = 0;
	static int[] arr = {0,0,0,0,0,0,0,1,1,1,1,1};//12个元素(将减取得格子标记为1)。与之前全排列不同,该数组具有重复元素
	static boolean vis[] = new boolean[12]; //标记元素有没有被访问
	public static void main(String[] args) {
		int[] path = new int[12];
		f(0,path);//全排列
		System.out.println(ans);
	}
	
	//1.对数组arr进行全排列
	private static void f(int n,int[] path) {
		if(n==12) {//已排列所有元素
			if(check(path)) {//判断合法性
				ans++;
				return;
			}
		}//if
		for(int i=0;i<12;i++) {
			
			if(i>0 && arr[i]==arr[i-1] && !vis[i-1]) //现在将要访问的元素与上一个元素相同,但是上一个元素没有访问,则退出本次循环。去重复
				continue;
			if(!vis[i]) {//将没有被用过的元素放入path
				vis[i]=true;
				path[n]=arr[i];
				f(n+1,path); //递归
				vis[i]=false;//回溯
			}
			
		}
		
	}
	
	//2.核对当前的顺序是否合法
	private static boolean check(int[] path) {
		//2.1 二维数组g记录当前排列中的元素
		int g[][] =new int[3][4];
		for(int i=0;i<3;i++) {
			for(int j=0;j<4;j++) {
				if(path[i*4+j]==1) {//遍历已排序的数组path
					g[i][j]=1;
				}else {
					g[i][j]=0;
				}
			}//for
		}//for
		
		//2.2 对数组g进行连通检验(5个1相连则为联通)。判断连通块的数目(为1则检验通过)
		int cnt=0;//记录当前连通块的数目
		for(int i=0;i<3;i++) {
			for(int j=0;j<4;j++) {
				if(g[i][j]==1) {
					dfs(g,i,j); //深度遍历(如果只有一个连通块,遍历一次即可)
					cnt++;
				}		
			}
		}
		return cnt==1; 
	}
	
	//3.对g进行深度优先遍历,从g[i][j]开始
	private static void dfs(int[][] g, int i, int j) {
		g[i][j]=0;//将当前访问的位置置为0,避免重复访问
		if(i-1>=0 && g[i-1][j]==1) dfs(g,i-1,j); //向上访问
		if(i+1<=2 && g[i+1][j]==1) dfs(g,i+1,j); //向下访问
		if(j-1>=0 && g[i][j-1]==1) dfs(g,i,j-1); //向左访问
		if(j+1<=3 && g[i][j+1]==1) dfs(g,i,j+1); //向右访问
	}
	
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值