平板涂色 抬手次数

#include <bits/stdc++.h>

using namespace std;

struct block
{
	int x1, y1, x2, y2, c;
}a[16];

int N;
int color[21] = {0};
int m;
int ans=16;
bool f[16][16] = { false };
int b[16] = {0};//砖块被涂的次数

bool cmp(block a,block b)
{
	if (a.x1 != b.x1)
		return a.x1 < b.x1;
	else
		return a.y1 < b.y1;
}

bool ok(int o)
{
	for (int i = 1; i <= N; i++)
		if (f[o][i] &&!b[i])//如果上紧挨着o砖块的i砖块没有涂色,就o砖块不能涂
			return false;
	return true;
}

void dfs(int o,int pq,int xx)//o抬手次数 pq涂过颜色的砖的数量 xx上次涂的颜色 
{  
	if (o >= ans)
		return;//当前涂色次数大于等于当前答案,直接退出
	if (pq == N)//涂完了砖
	{
		ans = o;
		return;
	}
	for (int i = 1; i <= m; i++)//枚举用的颜色
	{
		int qq = 0;//用i颜色涂过的砖数
		if (color[i] && i != xx)//如果有i这种颜色并且这不是上次涂的颜色,就要加抬手次数了
		{
			for (int j = 1; j <= N; j++)//枚举砖块
			{
				if (!b[j] && ok(j)&&a[j].c==i)//如果j砖块没涂过并且能涂
				{
					b[j] = 1;
					qq++;
				}
				else if (b[j] && a[j].c == i)
				{//递归的话同一个砖块可能被涂多次,但是也要算上去,不然如果没算上去的话,有可能在回溯的时候就会缺失明明可以涂却没有图上的情况
					b[j]++;
				}
			}
			if (qq > 0)
				dfs(o + 1, pq + qq, i);
			for (int j = N; j >= 1; j--)
			{
				if (b[j] == 1 && ok(j) && a[j].c == i)
				{
					b[j] = 0;
					qq--;
				}
				else if (b[j] > 1 && a[j].c == i)
				{
					b[j]--;
				}
			}
		}
	}
}

int main()
{
	scanf("%d", &N);
	for (int i = 1; i <= N; i++)
	{
		scanf("%d%d%d%d%d", &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2, &a[i].c);
		a[i].x1++; a[i].y1++;
		color[a[i].c]++;
	}
	for (int i = 1; i <= 20; i++)
		if (color[i])
			m = i;//记录最大的颜色编号
	sort(a + 1, a + N + 1,cmp);//以纵为先,横为后排序
	for (int i = 2; i <= N; i++)
		for (int j = i - 1; j >= 1; j--)//判断第i个方块是不是紧挨着上方的第j个方块
			if (a[i].x1==a[j].x2+1&&(a[i].y1>=a[j].y1&&a[i].y1<=a[j].y2
				                   ||a[i].y2>=a[j].y1&&a[i].y2<=a[j].y2))
				                     //要么左边点在中间,要么右边点在中间
				f[i][j] = true;
	dfs(0, 0, 0);
	printf("%d", ans);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值