JZOJ 3807. 【NOIP2014模拟8.25】地砖铺设

来源:互联网 发布:沈阳搜索引擎优化排名 编辑:程序博客网 时间:2024/04/28 20:35

Description

在游戏厅大赚了一笔的Randy 终于赢到了他想要的家具。乘此机会,他想把自己的房间好好整理一
下。
在百货公司,可以买到各种各样正方形的地砖,为了美观起见,Randy 不希望同样颜色的正方形地
砖相邻。所以他找到了Tio 来帮忙解决这件事情。
Tio 很快解决了这个任务。然而,出于某种强迫症,她希望在地上按照长宽划分成网格后,逐行逐
列每一块的颜色组成的序列的字典序最小。她希望你帮忙验证一下她的方案。

Input

第一行,包含两个整数N 和M,表示房间的长和宽。

Output

N 行,每行M 列,表示地砖铺设的方案,需要这个方案是字典序最小的合法方案。(可以认为,输出的方案去掉回车后形成的字符串字典序最小)

Sample Input

4 3

Sample Output

AAA
AAA
AAA
BCB

Data Constraint

• 对于分值为40 的子任务1,保证 NM<=5
• 对于分值为60 的子任务2,保证 NM<=100

Solution

  • 这道题看似简单,事实上打起来十分麻烦——

  • 这个方法是比较简单的,逐一逐一地填。

  • 如果填到一个正方形,则在它的右上角记录它的边长

  • 对于一个点,从它的左边、右边和上边算出它的最优字母,设为 k

  • 如果这个点左边的点有标记边长,且也为 k ,那么当前的点扩展为之前的正方形

  • 同时将 之前的边长+1 赋到当前点上

  • 如果不是,那么就直接填 k ,边长赋为 1 。

  • 这样不断操作,就成功填完啦!!

Code

#include<cstdio>#include<cstring>using namespace std;const int N=101,way[3][2]={{0,1},{-1,0},{0,-1}};int n,m,l=1,r;int f[N][N],g[N][N];bool bz[5];int main(){    scanf("%d%d",&n,&m);    while(true)    {        if(++r>m) l++,r=1;        if(l>n) break;        if(f[l][r]) continue;        int k=1;        memset(bz,false,sizeof(bz));        for(int i=0;i<3;i++)        {            int x=l+way[i][0],y=r+way[i][1];            if(!g[x][y] || i!=2) bz[f[x][y]]=true;        }        while(bz[k]) k++;        if(f[l][r-1]==k && g[l][r-1])         {            if(l+g[l][r-1]>n)            {                k++;                while(bz[k]) k++;                f[l][r]=k;                g[l][r]=1;                continue;            }            g[l][r]=g[l][r-1]+1;            for(int i=1;i<=g[l][r];i++) f[l+i-1][r]=k;            for(int i=1;i<g[l][r];i++) f[l+g[l][r]-1][r-g[l][r]+i]=k;        }else        {            f[l][r]=k;            g[l][r]=1;        }    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++) printf("%c",f[i][j]+'A'-1);        printf("\n");    }    return 0;}
1 0
原创粉丝点击