倪文迪带你学蓝桥杯2021寒假每日一题:1.6日第4题,C++、Java、Python三种代码

2021年寒假每日一题,2017~2019年的省赛真题。
本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供。

@

题目:方格分割 http://oj.ecustacm.cn/problem.php?id=1320
  2017年蓝桥杯软件类省赛C++语言大学A组第4题,一道填空题。

1、题目大意

  6x6的方格,沿着格子的边线剪开成两部分。要求这两部分的形状完全相同。
  试计算:一共有多少种不同的分割方法。注意:旋转对称的属于同一种分割法。

2、题解

  又是暴搜。第1题DFS,第2题BFS,第3题BFS,这题又回到DFS。下一题估计是BFS?
  
  倪文迪的话:“这道题可能上来会想到搜格子,但搜格子意味着更高的复杂度以及判连通的需要,本题似乎搜索要切开的边更优。由题意,这一条切割线必定经过图的中心点,那么我们一旦确定了半条到达边界的分割线,就能根据这半条对称画出另外半条。而由于结果中心对称性,搜索出来的个数应该除以4得出最终结论。在搜索过程中需要注意的是,我们搜索出的半条分割线不能同时经过关于中心对称的两个点,所以在标记时,需要将对称的点也标上。”
  中心点是(3,3),从(3,3)出发,向右、向左、向上、向下,四个方向DFS即可。
  
  下面给出三种语言的代码。
  据说Python组参加人少,容易得奖。Python真是好,Python呱呱叫。

3、C++代码

倪文迪的代码:

#include<bits/stdc++.h>
using namespace std;

int X[] = {0, -1, 1, 0, 0};
int Y[] = {0, 0, 0, -1, 1};

bool vis[10][10];
int res = 0;

void dfs(int x, int y)
{
	if(x == 0 || y == 0 || x == 6 || y == 6){
		res++;
		return ;
	}
	for(int i = 1 ; i <= 4 ; i++){   //上下左右四个方向
		x += X[i]; y += Y[i];        //走一步
		if(!vis[x][y]){       // 若该点未访问则继续深搜
			vis[x][y] = true;  //  当前的点标注为已访问
			vis[6 - x][6 - y] = true;
			dfs(x, y);         // 继续深搜
			vis[6 - x][6 - y] = false;
			vis[x][y] = false;
		}
		x -= X[i]; y -= Y[i];
	}
}

int main(){
	vis[3][3] = true;
	dfs(3, 3);
	cout << res / 4 << endl;

	return 0;
}

4、Java代码

http://oj.ecustacm.cn/用户20185012的代码:

public class Main {
 
    private static int ans = 0;
    private static int[][] dir = {{1,0},{-1,0},{0,1},{0,-1}};
    private static boolean[][] visit = new boolean[7][7];
 
    public static void main(String[] args) {
        visit[3][3] = true;
        dfs(3,3);
        System.out.println(ans / 4);
    }
 
    private static void dfs(int x,int y){
        if (x == 0 || y == 0 || x == 6 || y == 6){
            ans ++;
            return;
        }
        visit[x][y] = true;
        visit[6 - x][6 - y] = true;
        for (int i = 0; i < 4; i++) {
            int nx = x + dir[i][0];
            int ny = y + dir[i][1];
            if (nx < 0 || nx > 6 || ny < 0 || ny > 6)
                continue;
            if (!visit[nx][ny])
                dfs(nx,ny);
        }
 
        visit[x][y] = false;
        visit[6 - x][6 - y] = false;
    }
}

5、Python代码

http://oj.ecustacm.cn/用户20192031003的代码:

count = 0
vis = [[1] * 7 for i in range(7)]
dir = [(-1, 0), (1, 0), (0, -1), (0, 1)]
 
 
def dfs(x, y):
    global count
    if x == 0 or y == 0 or x == 6 or y == 6:
        count += 1
        return
    # 当前点和对称点都标注访问
    vis[x][y], vis[6 - x][6 - y] = 0, 0
    for i in range(0, 4):
        # 新坐标
        newx = x + dir[i][0]
        newy = y + dir[i][1]
        if newx < 0 or newx > 6 or newy < 0 or newy > 6:
            continue
        if vis[newx][newy]:
            dfs(newx, newy)
    vis[x][y], vis[6 - x][6 - y] = 1, 1
 
 
dfs(3, 3)
print(count//4)
原文地址:https://www.cnblogs.com/luoyj/p/14241723.html