1. 程式人生 > >洛谷P1790 矩形分割

洛谷P1790 矩形分割

題目描述
有一個長為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)
不是一樣的嗎,為什麼這樣可行?
這個問題讓你們自己去想!!!









































提示:
只從兩條邊開始搜尋