歌名 - 歌手
0:00

    【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;
    	}
    }
    
    
    posted @ 2018-05-22 12:09  无尽的蓝黄  阅读(191)  评论(0编辑  收藏  举报