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