pku 1691 Painting A Board
题目地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1691
题目大意:
就是给你一块大矩形,里面由一块块小矩形拼凑而成,通过给出小矩形的左上端点和右下端点的坐标来给出小矩形。
每块小矩形都有一个颜色属性(用一个数字来代表),问最少需要换多少次颜料就可以把所有矩形都涂上符合其自身属性的颜色。
涂色的规则:
一块矩形被涂色之前,还必须保证一个条件———与这块矩形相邻且在这块矩形的上面的所有矩形必须都被涂色了,这个条件满足后,这块矩形才能被涂色。
具体分析:
假设现在有:
矩形A,矩形B,矩形C(假设三个矩形的相邻情况是A与B相邻,B与C相邻)
颜色 1 2 1
我可以先拿颜色1对矩形A涂色,然后对矩形C涂色,再换颜料2,然后对矩形B涂色,一共换颜料换了2次。
我也可以拿颜色1对矩形A涂色,然后换颜料2对矩形B涂色,再换成颜料1对矩形C涂色,一共颜料换了3次。
其实就是一个DFS,用当前手上的颜料,从头到尾进行涂色,
如果一个矩形满足了 "当前颜料 == 该矩形颜色” &&“与该矩形相邻的上方矩形都被涂色”的话,
那么此时有两种选择,我可以选择涂该矩形,然后继续DFS。
也可以选择跳过,然后继续DFS。
如果上面两个条件无法同时满足的话,那么就只剩下一种选项,也就是跳过该矩形,然后继续DFS。
AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
#define N 100
struct Node
{
int l_x ,l_y;
int r_x , r_y;
int num;
};
int Mark[30], n,minn;
Node Gra[20];
int check(int pos) //判断pos上面的图形是否已经都被染色了
{
for(int i = 0 ;i < n ;i++ )
{
if(Gra[i].r_x == Gra[pos].l_x && Gra[i].l_y <= Gra[pos].r_y )
{
if(!Mark[i])
return 0;
}
}
return 1;
}
void DFS(int Color, int cnt,int ans)
{
if(cnt == n )
{
if(ans <= minn)
minn = ans;
// if(minn == 4)
//cout << "ok" << endl;
return ;
}
for( int i = 0 ;i < n ; i++)
{
if( !Mark[i] && check(i) )
{
if( Gra[i].num == Color )
{
Mark[i] = 1;
DFS( Color, cnt + 1 ,ans );
Mark[i] = 0;
}
else if( Gra[i].num != Color )
{
Mark[i] = 1;
DFS(Gra[i].num, cnt + 1, ans + 1);
Mark[i] = 0;
}
}
}
return ;
}
int main()
{
int cnt ;
cin >> cnt;
while( cnt-- )
{
cin >> n;
//memset(vis,0,sizeof(vis));
memset(Mark,0,sizeof(Mark));
for(int i = 0 ;i < n ;i++)
{
cin >> Gra[i].l_x >> Gra[i].l_y >> Gra[i].r_x >> Gra[i].r_y >> Gra[i].num;
//cout << Gra[i].l_x << Gra[i].l_y << Gra[i].r_x << Gra[i].r_y << Gra[i].num << endl;
}
minn = 999999;
DFS(-1,0,0);
cout << minn << endl;
}
return 0;
}