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

原文地址:https://www.cnblogs.com/chen1352/p/9071396.html