方格分裂-藍橋杯真題 DFS深度搜索(c++實現)

上文鏈接:藍橋杯真題之購物單(一分鐘巧解)


方格分割

6x6的方格,沿着格子的邊線剪開成兩部分。
要求這兩部分的形狀完全相同。
如下三圖就是可行的分割法。
試計算:
包括這3種分法在內,一共有多少種不同的分割方法。
注意:旋轉對稱的屬於同一種分割法。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

我的思路

  • 方格解析:該方格是7行7列的方格,紅橙兩連通方格圍繞(3,3)對稱。圖示如下。
    在這裏插入圖片描述
  • 思路:求解對稱的方式有多少種,可以利用DFS(深度遍歷)+遞歸思想,從中心對稱點開始走,一次走到結尾。過程爲:先標註當前點及對稱點,然後沿着當前點向四個方向走,走前判斷下步是否合法且是否已經走過,若合法,走到下步繼續重複此過程(遞歸實現)。直到走到邊界。注意點如下。
  1. 從該點走完整個路徑時回溯該點未走過的狀態,爲下次再走做準備。
  2. 因爲從對稱中心(3,3)向四個方向均可以走,如果開始沿着四個方向,比如向前一直走和向後一直走和向上一直帶走,向下一直走路徑相同,那麼最後結果旋轉之後呈現的對稱方式相同。所以最後得到的結果應該除以4。

算法展示

#include <iostream>
using namespace std;
typedef int It;//爲方便大範圍時修改進行類型定義 

It tag[7][7];//標註被訪問的點
It dire[4][2]={{0,1},{0,-1},{-1,0},{1,0}};//定義行走方向,上下左右 
It ans=0;//記錄結果,因爲(x,y)向四個方向走並標註對稱方格,旋轉之後沿四個方向走相同步驟其實是同一種對稱方式,所以結果應該除以4 
It lenDire = sizeof(dire)/sizeof(dire[0]);//獲取方向長度 
 
void dfs(It x,It y)//深度遍歷 
{
	if(x==0||y==0||x==6||y==6)//走到邊界,表示可以構成對稱方格,記錄該方式。 
	{
		ans++;
		return; 
	}
	//標註走過點 
	tag[x][y]=1;
	tag[6-x][6-y]=1;
	//改變方向行走
	for(int i =0;i<lenDire;i++)
	{
		int curX = x+dire[i][0];
		int curY = y+dire[i][1];
		//判斷當前走向是否合法且未走過
		if(tag[curX][curY]==1||(curX<0||curY<0||curX>6||curY>6))continue; 
		
		dfs(curX,curY);
	} 
	//查找完成後回溯標註點
	tag[x][y]=0;
	tag[6-x][6-y]=0;
}
 
int main()
{
	dfs(3,3); 
	cout<<ans/4<<endl;
	return 0;
}

下文鏈接:最大公共子串-藍橋杯真題 動態規劃(c++實現)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章