zoukankan      html  css  js  c++  java
  • [CQOI2007]矩形

    题目

    Description

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

    Input

    输入仅一行,为两个整数a,b。 1<=a<=6, 2<=b<=7

    Output

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

    Sample Input

    3 2

    Sample Output

    15

    思路

    这一题我们可以搜索;

    搜索每一条分割线,分割线一般从$(0,0)$ 到 $(n,m)$ ;

    分割线$(0,0)$ 表示坐标 $(1,1)$ 的左上角那个点;

    这样我们就可以搜索每一条分割线;

    枚举每条分割线的起点 $i$;

    题目要求至少有一个格子在原矩形的边界上,所以 $i$ 的范围必须满足 $1 leq i leq n$ 或 $m$ ;

    这样每一块都会有一个点在矩形的边界上了;

    那么找到答案的情况就是,分割线到了边界就,$ans++$ ;

    分割线起点在左边第一排的每次就 $dfs(i,1)$ ;

    分割线坐标的起点要保证不在边界上;

    还要注意的是,不能让分割线在当前排往回走,

    也就是,在$dfs$ 之前要记录 $f[i][0]=1$ 表示不能走,分割线是从 $1$ 到 $m$, 所以不能让它从 $1$ 到 $0$ ;

    这样就 $ok$ 了;

    代码

    #include<bits/stdc++.h>
    #define re register
    typedef long long ll;
    using namespace std;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f; 
    }
    ll n,m;
    ll a[5]={0,1,0,-1,0};
    ll b[5]={0,0,1,0,-1};
    ll f[10][10];
    ll ans,num;
    inline void dfs(ll x,ll y)
    {
        if(x<1||x>=n||y<1||y>=m)//如果分割线枚举到了边界
        {
            ans++;//答案加一
            return;
        }
        for(re ll i=1;i<=4;i++)//不断的找
        {
            ll xx=x+a[i],yy=y+b[i];
            if(f[xx][yy]==num)//分割线不能重合,所以当前点不能被走过
                continue;
            f[xx][yy]=num;
            dfs(xx,yy);
            f[xx][yy]=0;//回溯
        }
    }
    int main()
    {
        n=read(); m=read();//读入
        //横着找一遍
        for(re ll i=1;i<n;i++)//枚举,横坐标不能在边界上
        {
            num++;//一个不需要用memset,的小小优化
            f[i][0]=num;//不能回到在当前行左边的边界
                    //分割线是从 1到 m ,所以不能让它从 1 到 0
            f[i][1]=num;//标记走过
            dfs(i,1);
        }
        //竖着找一遍
        for(re ll i=1;i<m;i++)
        {
            num++;
            f[0][i]=num;//不能回到在当前列上边的边界
                    //分割线是从 1到 n ,所以不能让它从 1 到 0
            f[1][i]=num;//标记走过
            dfs(1,i);
        }
        printf("%lld
    ",ans);//输出答案
        //return 0;
    }
  • 相关阅读:
    黑马程序员--C语言基础之--数组、指针的基础知识
    黑马程序员--C语言基础之--变量、内部函数与外部函数
    黑马程序员--C语言基础之--printf函数
    黑马程序员--C语言基础之--scanf函数
    黑马程序员--C语言基础之--数据类型
    鉴定一张图片是否处理过
    图解JQUERY尺寸及位置定义
    谈谈对“渐进增强与平稳退化“的理解
    理解 JavaScript 作用域和作用域链
    编写更好的jQuery代码的建议
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/13557201.html
Copyright © 2011-2022 走看看