你好呀,我是灰小猿,一个超会写bug的程序猿!
欢迎大家关注我的专栏“每日蓝桥”,该专栏的主要作用是和大家分享近几年蓝桥杯省赛及决赛等真题,解析其中存在的算法思想、数据结构等内容,帮助大家学习到更多的知识和技术!
标题:剪邮票
如【图1.jpg】有12张连在一起的十二生肖的邮票
现在你要从中剪下五张来,要求五张必须是连续的
【只连接一个角不算连接】
如【图2.jpg】和【图3.jpg】中的粉色部分就是合格的剪取
请你计算一下,一共有多少种不同的剪取方法。
请填写表示方案数目的整数,
注意:你提交的应该是一个整数,不要填写任何多余内容或说明性文字
解题思路:
本题在求解上的思路是:首先将12个元素标记出来,粉色格子标记为1,白色格子标记为0,那么我们可以假设数组是{0,0,0,0,0,0,0,1,1,1,1,1},可以理解为对这12个元素进行全排列,由于存在重复元素,因此在排列之后,需要去除重复排列,然后将结果映射成二维数组,判断该二维数组的连通性,如果连通性为1,则符合要求,否则不符合要求,结果不加一。
答案源码:
package 一六年省赛真题; import java.util.HashSet; public class Year2016_Bt7 { static HashSet<String> hashSet = new HashSet<String>(); static int ans = 0; public static void main(String[] args) { int [] arr = {0,0,0,0,0,0,0,1,1,1,1,1}; f(arr, 0); System.out.println(ans); } public static void f(int [] arr,int k) { if (k == arr.length) { //如果hashset中不包含已经排列好的数组,则进行连通性判断 // System.out.println(hashSet.add(arrToStr(arr))); if (hashSet.add(arrToStr(arr))) { //如果连通,则答案加一 if (check(arr)) { ans++; } } return; } for (int i = k; i < arr.length; i++) { int t = arr[k]; arr[k] = arr[i]; arr[i] = t; //递归确定下一个元素 f(arr, k+1); //回溯 t = arr[k]; arr[k] = arr[i]; arr[i] = t; } } //数组 private static String arrToStr(int[] arr) { String s = ""; for (int i : arr) { s += i; } return s; } /** * 判断数组构成的二维数组是否具有连通性 * */ private static boolean check(int[] arr) { int [][] matrix = new int[3][4]; //将一维数组映射成二维数组 for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { if (arr[i*4+j]==1) { matrix[i][j] = 1; }else { matrix[i][j] = 0; } } } int count = 0; //从二维数组的每一个元素开始进行连通性判断 for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { if (matrix[i][j]==1) { dfs(matrix,i,j); count++; } } } //如果只有一个连通图,则该情况成立 return count==1; } //对元素进行深搜 private static void dfs(int[][] matrix, int i, int j) { matrix[i][j] = 0; //对该坐标的四个方向进行判断,如果某个方向可以走,并且该方向上的那个坐标值是1,则走到这一个格 if(i-1>=0&&matrix[i-1][j]==1) dfs(matrix, i-1, j); if(i+1<=2&&matrix[i+1][j]==1) dfs(matrix, i+1, j); if(j-1>=0&&matrix[i][j-1]==1) dfs(matrix, i, j-1); if(j+1<=3&&matrix[i][j+1]==1) dfs(matrix, i, j+1); } }
输出样例: