【题解】P1283 平板涂色

题目链接:P1283 平板涂色

题面

题目描述

CE 数码公司开发了一种名为自动涂色机(APM)的产品。它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色。

为了涂色,APM 需要使用一组刷子。每个刷子涂一种不同的颜色 C i C_i Ci 。APM 拿起一把有颜色 C i C_i Ci 的刷子,并给所有颜色为 C i C_i Ci 且符合下面限制的矩形涂色:

为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色。例如图中矩形 F F F 必须在 C C C D D D 涂色后才能涂色。注意,每一个矩形必须立刻涂满,不能只涂一部分。

写一个程序求一个使 APM 拿起刷子次数最少的涂色方案。注意,如果一把刷子被拿起超过一次,则每一次都必须记入总数中。

输入格式

第一行为矩形的个数 N N N。下面有 N N N 行描述了 N N N 个矩形。每个矩形有 5 5 5 个整数描述,左上角的 y y y 坐标和 x x x 坐标,右下角的 y y y 坐标和 x x x 坐标,以及预定颜色。

平板的左上角坐标总是 ( 0 , 0 ) (0,0) (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 ≤ C i ≤ 20 1\le C_i \le 20 1Ci20 0 ≤ x i , y i ≤ 99 0 \le x_i,y_i \le 99 0xi,yi99 1 ≤ N ≤ 16 1\le N \le 16 1N16

思路

这题数据范围很小,可以直接搜索。

搜索每一个矩形有没有被涂过,如果没有涂过,

先判断这个矩形能不能涂,用 c h e c k check 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值