題目鏈接:P1283 平板塗色
題面
題目描述
CE 數碼公司開發了一種名為自動塗色機(APM)的產品。它能用預定的顏色給一塊由不同尺寸且互不覆蓋的矩形構成的平板塗色。
為了塗色,APM 需要使用一組刷子。每個刷子塗一種不同的顏色 Ci 。APM 拿起一把有顏色 Ci 的刷子,並給所有顏色為 Ci 且符合下面限制的矩形塗色:

為了避免顏料滲漏使顏色混合,一個矩形只能在所有緊靠它上方的矩形塗色后,才能塗色。例如圖中矩形 F 必須在 C 和 D 塗色后才能塗色。注意,每一個矩形必須立刻塗滿,不能只塗一部分。
寫一個程序求一個使 APM 拿起刷子次數最少的塗色方案。注意,如果一把刷子被拿起超過一次,則每一次都必須記入總數中。
輸入格式
第一行為矩形的個數 N。下面有 N 行描述了 N 個矩形。每個矩形有 5 個整數描述,左上角的 y 坐標和 x 坐標,右下角的 y 坐標和 x 坐標,以及預定顏色。
平板的左上角坐標總是 (0,0)。
輸出格式
一個整數,表示拿起刷子的最少次數。
輸入輸出樣例
輸入 #1
7
0 0 2 2 1
0 2 1 6 2
2 0 4 2 1
1 2 4 4 2
1 4 3 6 1
4 0 6 4 1
3 4 6 6 2
輸出 #1
3
說明/提示
\(1\le C_i \le 20\),\(0 \le x_i,y_i \le 99\),\(1\le N \le 16\)。
思路
這題數據范圍很小,可以直接搜索。
搜索每一個矩形有沒有被塗過,如果沒有塗過,
先判斷這個矩形能不能塗,用check函數來判斷,代碼內的注釋已經給得非常詳細了。
如果能塗的話,再看是不是和刷子顏色一樣,如果不是,就++。
代碼
#include <iostream>
using namespace std;
int n, ans, x1[20], _y1[20], x2[20], y2[20], color[20];
//y1是關鍵字,必須在前面加一個下划線
bool visit[20];
void search(int, int, int);
bool check(int);
int main()
{
cin >> n;
ans = n; //先把ans設為一個(在本題中)最大的值
for (int i = 1; i <= n; i++) {
cin >> _y1[i] >> x1[i] >> y2[i] >> x2[i] >> color[i]; //先輸入y坐標,再輸入x坐標
}
search(0, 0, -1);
cout << ans << endl;
return 0;
}
void search(int tot, int finish, int col)
{
if (tot >= ans)
return; // 如果總數已經大於ans的值了,就可以不用繼續了
if (finish == n)
ans = tot; //如果已經搜索完畢了,就直接把tot的值賦給ans
for (int i = 1; i <= n; i++)
if (!visit[i] && check(i)) {
visit[i] = true;
if (color[i] == col) { //如果找到了是這個矩形那就給它塗色
search(tot, finish + 1, color[i]);
}
else { //如果找到的矩形顏色不一樣,就finish++,繼續塗色
search(tot + 1, finish + 1, color[i]);
}
visit[i] = false; //回溯
}
}
bool check(int k)
{
for (int i = 1; i <= n; i++)
if (!visit[i] //如果循環到的矩形沒塗過色
&& _y1[i] == y2[k] //判斷要塗色的矩形是否下好在循環到的矩形下方
//可通過判斷循環到的矩形的下面那條邊的縱坐標是否與
//要塗色的矩形上面那條邊的縱坐標相等
&& ((x1[i] >= x1[k] && x1[i] <= x2[k]) //循環到的矩形的左邊界在要塗色的矩形左右邊界之間
|| (x2[i] >= x1[k] && x2[i] <= x2[k]))) //循環到的矩形的右邊界在要塗色的矩形左右邊界之間
return false;
return true;
}
