信息学奥赛一本通T1445-平板涂色

目录

题目描述

输出格式

样例输入

样例输出

具体代码如下


题目描述

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

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

信息学奥赛一本通T1445-平板涂色

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

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

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

颜色号为1到20的整数。

平板的左上角坐标总是(0, 0)。

坐标的范围是0..99。N小于16。

输出格式

拿起刷子的最少次数。

样例输入

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

样例输出

3

具体代码如下

import java.util.Scanner;
 
public class Main {
// 录入有几个矩形
    static int n;
    // 创了个类 用数组存着
    static LR lr[];
    // good[i][j] 使用这来判断j矩形是否在i矩形下面 并且挨着
    static int good[][];
    // good1[j] 这个是说 j矩形上面 有几个矩形挨着他
    static int good1[];
    // 留个记号 不让dfs走回头路
    static boolean bu[];
    // 换刷子的初始值 一定要搞大些 因为后面取的是小的
    static int zong = 100;
 
    public static void main(String[] args) {
        // 录入
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        lr = new LR[n + 1];
        good = new int[n + 1][n + 1];
        good1 = new int[n + 1];
        bu = new boolean[n + 1];
        for (int i = 1; i <= n; i++) {
            int q = scanner.nextInt();
            int q1 = scanner.nextInt();
            int q2 = scanner.nextInt();
            int q3 = scanner.nextInt();
            int q4 = scanner.nextInt();
            lr[i] = new LR(q, q1, q2, q3, q4);
        }
        // 看什么矩形 与 什么矩形之间有紧密的关系 矩形自身的关系
        kjj();
        // 深入优先搜索 的使用
        dfs(0, 0, 0);
        System.out.println(zong);
    }
 
    static void kjj() {
        // 两层for循环看 所有矩形之间的关系 矩形的自身与别的关联
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                // 共三个条件 第一个条件是一个矩形下面和一个矩形上面挨着 还有两个是(其实两个是一个总的)这个总的意思是两个矩形紧挨着
                if (lr[i].yb == lr[j].ya && !(lr[i].xa > lr[j].xb | lr[i].xb < lr[j].xa)) {
                    // 矩形i和矩形j要是满足上面条件 就赋为1 就说明i下面有j这个矩形
                    good[i][j] = 1;
                    // 说明j这个矩形上面有几个矩形
                    good1[j]++;
                }
            }
        }
    }
 
    // 大法师 dfs 深度优先搜索 a是刷了几个矩形 b是拿了几次刷子 ys是刷子的颜色
    static void dfs(int a, int b, int ys) {
        // 这两个if都是节支 可提高效率
 
        // 这个是 拿刷子的次数比上次多则 直接退出方法 提高效率
        if (b > zong) {
            return;
        }
        // 这个是刷的矩形数 等于 总的矩形数时 退出方法
        if (a == n) {
            zong = b;
            return;
        }
 
        // 下面相当于 给矩形刷漆
        for (int i = 1; i <= n; i++) {
 
            if (!bu[i] & good1[i] == 0) {
                // 因为是遍历了所有矩形 所以留标记 防止回头 这就相当于给这个矩形刷漆了
                bu[i] = true;
                for (int j = 1; j <= n; j++) {
                    if (good[i][j] == 1) {
                        // 将矩形j上面的 限制减少一个
                        good1[j]--;
                    }
                }
 
                // 看颜色
                if (lr[i].ys == ys) {
                    dfs(a + 1, b, ys);
                } else {
                    dfs(a + 1, b + 1, lr[i].ys);
                }
 
                bu[i] = false;
                for (int j = 1; j <= n; j++) {
                    if (good[i][j] == 1) {
                        good1[j]++;
                    }
                }
            }
        }
    }
}
 
class LR {
    int ya, xa, yb, xb, ys;
 
    public LR(int ya, int xa, int yb, int xb, int ys) {
        this.ya = ya;
        this.xa = xa;
        this.yb = yb;
        this.xb = xb;
        this.ys = ys;
    }
 
}

原题链接:

信息学奥赛一本通T1445-平板涂色

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值