首页 > 代码库 > poj 1691 Painting A Board(dfs,拓扑排序)

poj 1691 Painting A Board(dfs,拓扑排序)

http://poj.org/problem?id=1691


大致题意:给出n个矩形,其参数有左上角顶点坐标,右下角顶点坐标以及该矩形所涂颜色。规定是涂当前矩形当且仅当它上面的矩形都已经被涂了色。若当前涂的颜色和上一个所涂的不同,就要换一种颜色的刷子。问应该按怎样的顺序给这n个矩形涂色使换的刷子总数最少。


思路:显然涂色是有先后顺序的,就很容易想到拓扑排序。那么首先根据矩形相交建立一个矩形之间的有向图,然后求出所有的拓扑排序,同时比较出所换刷子最少的即可。


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8

using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10;

struct node
{
	int x1,y1,x2,y2;
	int col;
}rec[20];
int n;
int Map[20][20];
int in[20],vis[20];
int ans;

//求出所有的拓扑排序,每次找一个未访问的入度为0的点进行拓扑,最后要更改回来状态
void dfs(int num, int pre_col, int col)
{
	if(col > ans)
		return;
	if(num == n)
	{
		if(col < ans)
			ans = col;
		return;
	}

	for(int i = 1; i <= n; i++)
	{
		if(!vis[i] && in[i] == 0)
		{
			vis[i] = 1;
			for(int j = 1; j <= n; j++)
				if(Map[i][j] == 1)
					in[j]--;

			if(rec[i].col == pre_col)
				dfs(num+1,pre_col,col);
			else dfs(num+1,rec[i].col,col+1);

			vis[i] = 0;
			for(int j = 1; j <= n; j++)
				if(Map[i][j] == 1)
					in[j]++;
		}
	}
}

int main()
{
	int test;
	scanf("%d",&test);
	while(test--)
	{
		scanf("%d",&n);
		for(int i = 1; i <= n; i++)
		{
			scanf("%d %d %d %d %d",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2,&rec[i].col);
		}
		memset(Map,0,sizeof(Map));
		memset(in,0,sizeof(in));
		memset(vis,0,sizeof(vis));
		ans = INF;

		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= n; j++)
			{
				if(i == j) continue;
				//注意判断矩形相交,没考虑周全,1WA。
				if(rec[j].x2 == rec[i].x1 && ( (rec[j].y2 > rec[i].y1 && rec[j].y2  <= rec[i].y2) || 
				(rec[j].y1 < rec[i].y2 && rec[j].y1 >= rec[i].y1)))
				{
					Map[j][i] = 1;
					in[i] += 1;
				}
			}
		}
		dfs(0,-1,0);
		printf("%d\n",ans);
	}
	return 0;
}