第七届蓝桥杯省赛--剪邮票

一、问题描述

  如【图1.jpg】, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。请你计算,一共有多少种不同的剪取方法。请填写表示方案数目的整数。
  注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

                             

二、题目类型:结果填空、全排列、DFS/BFS

 

三、解题思路及代码

  首先,要给自己一个小小的肯定~耶,今天学习dfs、bfs可终于敲出来了(大佬轻喷,我的算法能力级别停留在幼儿园阶段),果然知识的引体很重要,《算法笔记》这本书真的很赞!

  我的解法比其他博主写的方法要笨上许多,大家看看思路就行,嘿嘿。

  思路:初始化 3*4 的二维数组和状态数组,对于这12个空,全排列出所有五个空的组合,在二维数字中把这五个空置为 1 ,并对此组合的进行bfs/dfs连通判断(用状态数组进行判断),把所有可以连通的组合加起来就是答案。

 1 import java.util.ArrayDeque;
 2 import java.util.Scanner;
 3 
 4 public class CutTheStamps {
 5     static int n;// n行
 6     static int m;// m列
 7     static int[][] arr;// 邻接矩阵
 8     static boolean zt[][];// 状态数组
 9     static int[] X = new int[] { 1, -1, 0, 0 };// 增量数组
10     static int[] Y = new int[] { 0, 0, 1, -1 };
11 
12     public static void main(String[] args) {
13         Scanner input = new Scanner(System.in);
14         n = input.nextInt();
15         m = input.nextInt();
16         arr = new int[n][m];// 默认0
17         zt = new boolean[n][m];// 默认false
18         int sum = 0;// 统计符合题目条件的剪法
19         // 全排列
20         for (int a = 0; a < 12; a++) {
21             for (int b = a + 1; b < 12; b++) {
22                 for (int c = b + 1; c < 12; c++) {
23                     for (int d = c + 1; d < 12; d++) {
24                         for (int e = d + 1; e < 12; e++) {
25                             arr[a / 4][a % 4] = 1;
26                             arr[b / 4][b % 4] = 1;
27                             arr[c / 4][c % 4] = 1;
28                             arr[d / 4][d % 4] = 1;
29                             arr[e / 4][e % 4] = 1;
30                             bfs(a / 4, a % 4);// 从a开始搜索
31                             int count = counts(zt);// 计算此组合剪法,邮票的连通数
32                             if (count == 5) {// 等于5说明5张邮票都连通
33                                 sum++;
34                             }
35                             zt = new boolean[n][m];// 重置,准备下一个组合的判断
36                             arr = new int[n][m];// 重置,准备下一个组合的判断
37                         }
38                     }
39                 }
40             }
41         }
42         System.out.println(sum);
43     }
44 
45     // 判断bfs后的状态数组中有多少个true
46     public static int counts(boolean[][] zt) {
47         int count = 0;
48         for (int i = 0; i < n; i++) {
49             for (int j = 0; j < m; j++) {
50                 if (zt[i][j]) {
51                     count++;
52                 }
53             }
54         }
55         return count;
56     }
57 
58     // 判断当前位置是否可以连通(入队列)
59     public static boolean judge(int x, int y) {
60         if (x >= n || x < 0 || y >= m || y < 0)
61             return false;
62         if (arr[x][y] == 0 || zt[x][y])
63             return false;
64         return true;
65     }
66 
67     public static void bfs(int x, int y) {
68         ArrayDeque<Node> queue = new ArrayDeque<Node>();
69         Node node = new Node(x, y);
70         queue.add(node);// 入队
71         zt[x][y] = true;// 状态设置为已访问
72         while (!queue.isEmpty()) {
73             Node top = queue.poll();// 取出队头元素
74             for (int i = 0; i < 4; i++) {// 判断上、下、左、右四个位置是否可以入队
75                 int newX = top.x + X[i];
76                 int newY = top.y + Y[i];
77                 if (judge(newX, newY)) {
78                     Node n = new Node(newX, newY);
79                     queue.add(n);// 入队
80                     zt[newX][newY] = true;// 状态设置为已访问
81                 }
82             }
83         }
84     }
85 }
86 
87 class Node {
88     int x;
89     int y;
90 
91     public Node(int x, int y) {
92         this.x = x;
93         this.y = y;
94     }
95 }

四、反思与总结

  这类题目我觉得有点绕,要多练习、多思考。冲鸭~

转载于:https://www.cnblogs.com/crush-u-1214/p/10567706.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值