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