【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;
}
}