1025 [CQOI2007]矩形RECT bfs

链接:https://ac.nowcoder.com/acm/contest/23156/1025
来源:牛客网

题目描述

给一个a*b矩形,由a*b个单位正方形组成。你需要沿着网格线把它分成分空的两部分,每部分所有格子连通,且至少有一个格子在原矩形的边界上。“连通”是指任两个格子都可以通过水平或者竖直路径连在一起。 求方案总数。例如3*2的矩形有15种方案。
   

输入描述:

输入仅一行,为两个整数a,b。1≤a≤61\leq a\leq61a6, 2≤b≤72\leq b\leq 72b7

输出描述:

输出仅一行,即方案总数。
示例1

输入

复制
3 2

输出

复制
15
示例2

输入

复制
3 3

输出

复制
52

分析

这道题,我看着感觉很难。。这种枚举方案数嘴不擅长了

然后听了雨巨的,我也半天没搞懂。。。只能说这种题真的不擅长

然后才知道是bfs。枚举一条线的走路方式就可以了。是从左上角的顶点出发枚举每个边界走到另一个边界的所有情况

但过程中还是不理解到底是怎么把所有情况都枚举到的,因为题解只枚举了上边界和左边界,我直接感觉上边界走到左边界和左边界走到上边界不是重合了吗。。而且右边界和下边界没有枚举到

其实可以想一想,正常来讲,要上边界走到下面两个边界,左边界走到另外三个边界,然后下边界走到右边界,才是所有情况。

但下边界走到右边界,相当于上边界走到左边界,这两个情况重合了。。。所以可以直接枚举左边界和上边界。。。。

其实wa了很久,才知道dxdy写错了。。而且i应该是1到n-1。j应该是1到m-1


int dy[] = {1,-1,0,0,-1,-1,0,1,1};
int dx[] = {0,0,-1,1,0,-1,-1,-1,0};

/*文档区


*/

//-------------------------代码----------------------------

//#define int LL
const int N = 20;
int n,m;

int vis[N][N];
int num = 0;
void dfs(int x,int y) {
    if(x == 0 || y == 0 || x == n || y == m) {
        num ++ ;
        rt;
    }
    for(int i = 0;i<4;i++) {
        int xx = x + dx[i],yy = y + dy[i];
        if(xx<0 || yy < 0 || xx > n || yy > m ) continue;
        if(vis[xx][yy])continue;
        vis[xx][yy] = 1;
        dfs(xx,yy);
        vis[xx][yy] = 0;
    }
}

void solve()
{
     cin>>n>>m;
//     V<V<int>>mp(n+1,V<int>(m+1));
     for(int i = 1;i<n;i++) {
         vis[i][0] = vis[i][1] = 1;
         dfs(i,1);
         vis[i][0] = vis[i][1] = 0;
     }
    for(int j=1;j<m;j++){
        vis[0][j] = vis[1][j] = 1;
        dfs(1,j);
        vis[0][j] = vis[1][j] = 0;
    }
    cout<<num<<endl;
}

signed main(){
    clapping();TLE;
    
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

posted @ 2022-07-03 21:31  er007  阅读(26)  评论(0编辑  收藏  举报