hdu 5113 Black And White

传送门:2014北京区域赛B题

       给定一个n×m大小的棋盘,现在有k种颜色的涂料,每种颜色的涂料给一定的数量,要求给所有格子上色,要求任意两个格子之间不能同色,问能否做到,若能请输出任意一种上色方案。


       坑了我好几天的题目,不想要用深搜,就想构造,结果各种跪跪跪,找不到一种能完全符合要求的构造方案,最后发现把多种构造混在一起就行了 sigh~~

       将棋盘黑白染色

       方案(一):将颜料按数量从大到小排序,然后先涂黑块再涂白块

       方案(二):将颜料按数量从大到小排序,然后先涂白块再涂黑块

       方案(三):先涂黑块再涂白块,上色顺序,把最大的涂掉,然后从小到大按颜料数量涂

/******************************************************
 * File Name:   b.cpp
 * Author:      kojimai
 * Create Time: 2014年12月05日 星期五 13时24分16秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int FFF = 30;
int n,m,k;
struct node
{
	int num,col;
	bool operator < (const node &a) const{
		return num > a.num;
	}
}p[FFF];
int col[7][7];

void solve1()
{
	int now = 0,t = p[now].num;
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if((i+j)%2==1)
			{
				col[i][j] = p[now].col;
				if(!(--t))
				{
					now++;
					t = p[now].num;
				}
			}
		}
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if((i+j)%2==0)
			{
				col[i][j] = p[now].col;
				if(!(--t))
				{
					now++;
					t = p[now].num;
				}
			}
		}
	}
}
void solve2()
{
	int now = 0,t = p[now].num;
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if((i+j)%2==0)
			{
				col[i][j] = p[now].col;
				if(!(--t))
				{
					now++;
					t = p[now].num;
				}
			}
		}
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if((i+j)%2==1)
			{
				col[i][j] = p[now].col;
				if(!(--t))
				{
					now++;
					t = p[now].num;
				}
			}
		}
	}
}

void solve3()
{
	int now = 0,t = p[now].num;
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if((i+j)%2 == 1)
			{
				col[i][j] = p[now].col;
				t--;
				if(!t)
				{
					if(now == 0)
						now = k - 1;
					else
						now--;
					t = p[now].num;
				}
			}
		}
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if((i+j)%2 == 0)
			{
				col[i][j] = p[now].col;
				t--;
				if(!t)
				{
					if(now == 0)
						now = k - 1;
					else
						now--;
					t = p[now].num;
				}
			}
		}
	}
}
bool judge()
{
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if(i < n && col[i][j] == col[i+1][j]) return false;
			if(j < m && col[i][j] == col[i][j+1]) return false;
		}
	}
	return true;
}

void print()
{
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			if(j>1)
				cout<<' ';
			cout<<col[i][j];
		}
		cout<<endl;
	}
}

int main()
{
	int keng,Case = 1;
	scanf("%d",&keng);
	while(keng--)
	{
		scanf("%d%d%d",&n,&m,&k);
		for(int i = 0;i < k;i++)
		{
			scanf("%d",&p[i].num);
			p[i].col = i+1;
		}
		sort(p,p+k);
		printf("Case #%d:\n",Case++);
		if((n*m+1)/2 < p[0].num)
		{
			printf("NO\n");
			continue;
		}
	
		solve1();
		bool flag = judge();

		if(!flag)
		{
			solve2();
			flag = judge();
		}

		if(!flag)
		{
			solve3();
			flag = judge();
		}

		/*if(!flag)
		{
			printf("Case #%d:\n",Case);
			cout<<" num = "<<p[0].num<<endl;
			print();
		}*/
		//solve3();

		printf("YES\n");
		print();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值