【NOIP2014模拟8.25】地砖铺设

题目

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

分析

贪心,
逐行逐列枚举,
枚举当前点(当前点没有字母)放什么字母,根据最优策略,显然放的字母越小答案越优。
假设枚举到点\((i,j)\),
那么\((i,j)\)的字母一定不能等于\((i,j+1)\)的和\((i-1,j)\)的,
但是如果\((i,j)\)的可以赋值的最优字母等于\((i,j-1)\)的,并且\((i,j-1)\)是某个正方形的右上角,那么就可以将这个正方形扩大,向右下角扩大一格,否则,\((i,j)\)直接赋值。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=105;
using namespace std;
int a[N][N],n,m,b[N][N];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(!a[i][j])
            for(int k=1;k<=4;k++)
                if(k!=a[i-1][j] && k!=a[i][j+1])
                {
                    if(b[i][j-1] && k==a[i][j-1] && i+b[i][j-1]+1-1<=n)
                    {
                        int len=b[i][j-1]+1;
                        for(int l=i;l<=i+len-1;l++) 
                            a[l][j]=k;
                        for(int l=j-len+1;l<=j;l++)
                            a[i+len-1][l]=k;
                        b[i][j]=b[i][j-1]+1;
                        break;
                    }
                    else
                    if(k!=a[i][j-1])
                    {
                        a[i][j]=k;
                        b[i][j]=1;
                        break;
                    }
                }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++) printf("%c",a[i][j]+64);
        cout<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9071396.html