洛谷P1790 矩形分割
阿新 • • 發佈:2018-11-25
題目描述
有一個長為a,寬為b的矩形(1≤a≤6,2≤b≤6)。可以把這個矩形看作是a*b個小方格。
我們現在接到了這樣的一個任務:請你計算出,把這個矩形分割成兩個部分的方法總數。
你不是可以任意地分割這個大的矩形, 必須滿足:
分割後,每個部分,至少各自均有一個方格是在大矩形的最外邊上(即大矩形最外面一環的方格)。
輸入輸出格式
輸入格式:
輸入檔案僅包含兩個數字,a和b。
輸出格式:
輸出僅有1行,這一行僅有一個整數,表示分割的方案總數。
輸入輸出樣例
輸入樣例#1:
3 2
輸出樣例#1:
15
看到這題,我十分的束手無策,但是當我認真看完題目之後,發現了
(1<=a,b<=6)
這就為暴力提供了很好的機會
我們可以把這個矩陣想象成一個無向圖,然後就是求從一個邊界點 出發(不走邊界點)到另外一個邊界點的方案數
但是這樣可能行不通,因為你很難判斷這個方案是否走過,我一開始想用狀態壓縮來判斷這種方案是否出現過,後來發現沒有這個必要
我們只需要從矩陣一條長和一條寬上的每個點出發,求出到另外一個邊界點的方案數,記得不要從矩陣的端點出發
#include<cstdio> #include<cstring> using namespace std; const int N=1e1; int n,m; int ans=0; int dx[4]={-1,0,1,0};//上下左右四個方向 int dy[4]={0,1,0,-1}; bool map[N][N];//map判斷這個點有沒有走過 void dfs(int x,int y) { map[x][y]=1;//把這個點設定為走過 if(x==1||y==m||x==n||y==1){//如果到了邊界點 ans++; map[x][y]=0; return; } for(int i=0;i<4;++i){//往四個方向搜尋 int xx=x+dx[i],yy=y+dy[i]; if(xx<1||yy<1||xx>n||yy>m||map[xx][yy])continue; dfs(xx,yy); } map[x][y]=0;//回溯 } int main() { scanf("%d%d",&n,&m); n++;m++;//要多加一個點 memset(map,0,sizeof(map));//初始化所有的點都是可以走的 for(int i=2;i<n;++i){ map[i][1]=1;//把這個點設定為不能走 dfs(i,2);//直接從下一個點開始搜尋,保證不會走邊界 map[i][1]=0;//回溯 } for(int i=2;i<m;++i){//同上 map[1][i]=1; dfs(2,i); map[1][i]=0; } printf("%d\n",ans);//輸出 return 0; }
好了,文章就到這裡了
其實,我一開始想這個程式碼的時候發現了一個似乎存在的bug
那就是我從//(x,y)表示(行,列)
(1,2)->(2,2)->(2,1)
和
(2,1)->(2,2)->(1,2)
不是一樣的嗎,為什麼這樣可行?
這個問題讓你們自己去想!!!
提示:
只從兩條邊開始搜尋