趣味编程题之Blocked Billboard

本文介绍了一个计算问题,通过给定的两个广告牌和一辆卡车的位置坐标,计算卡车遮挡后两个广告牌剩余的可见总面积。使用Java实现算法并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

During long milking sessions, Bessie the cow likes to stare out the window of her barn at two huge rectangular billboards across the street advertising “Farmer Alex’s Amazingly Appetizing Alfalfa” and “Farmer Greg’s Great Grain”. Pictures of these two cow feed products on the billboards look much tastier to Bessie than the grass from her farm.
One day, as Bessie is staring out the window, she is alarmed to see a huge rectangular truck parking across the street. The side of the truck has an advertisement for “Farmer Smith’s Superb Steaks”, which Bessie doesn’t quite understand, but she is mostly concerned about the truck potentially blocking the view of her two favorite billboards.

Given the locations of the two billboards and the location of the truck, please calculate the total combined area of both billboards that is still visible. It is possible that the truck obscures neither, both, or only one of the billboards.
在长时间的挤奶环节,Bessie喜欢盯着她谷仓窗口的两个巨大的长方形的广告牌,该街头广告牌上书:“农夫亚历克斯好吃的香苜蓿”和“农民格雷戈的大量粮食”。广告牌上的这两种奶牛饲料产品看起来比Bessie她自己农场的草料味道更好。
有一天,当Bessie正盯着窗外时,她惊恐地看到一辆巨大的长方形卡车停在街对面。卡车的一侧有一个广告,上书:“农场主史密斯的超级牛排”,Bessie对此并不十分了解,但她最担心的是卡车可能挡住了她最喜欢的两个广告牌的视野。
考虑到两个广告牌的位置和卡车的位置,请计算仍然可见的两个广告牌的剩余总面积。对于两个广告牌,卡车可能一个都不遮盖,也可能都遮盖,也可能只遮盖一个。

INPUT FORMAT (file billboard.in):

The first line of input contains four space-separated integers: x1x1 y1y1 x2x2 y2y2, where (x1,y1)(x1,y1) and (x2,y2)(x2,y2) are the coordinates of the lower-left and upper-right corners of the first billboard in Bessie’s 2D field of view. The next line contains four more integers, similarly specifying the lower-left and upper-right corners of the second billboard. The third and final line of input contains four integers specifying the lower-left and upper-right corners of the truck. All coordinates are in the range -1000 to +1000. The two billboards are guaranteed not to have any positive area of overlap between themselves.

输入的第一行包含四个整数:x1、 y1, X2、 y2,从Bessie的二维视角来看,(x1,y1)(x2,y2)是分别是第一个广告牌的左下,右上坐标。下一行包含四个整数,同样地指明为第二个广告牌的左下和右上坐标。输入的第三行也即最后一行同样包含四个整数,它们指明的是卡车的左下和右上坐标。所有坐标值都在 -1000到1000的范围内。两个广告牌保证不会有任何重叠区域。

OUTPUT FORMAT (file billboard.out):

Please output the total combined area of both billboards that remains visible.
请输出仍然可见的两个广告牌的剩余总面积

SAMPLE INPUT:

1 2 3 5
6 0 10 4
2 1 8 3
SAMPLE OUTPUT:

17
Here, 5 units of area from the first billboard and 12 units of area from the second billboard remain visible.
这里,第一个广告牌有5单位的面积可视,第二个有12单位,共计17单位
Problem credits: Brian Dean

解析:

矩形1左下坐标 (left1, bottom1),右上(right1, top1)
矩形2左下坐标 (left2, bottom2),右上(right2, top2)
横坐标重叠长度overlapX = (right1-left1)+(right2-left2) - [max(right1,right2) - min(left1,left2)]
纵坐标重叠长度overlapY=(top1-bottom1)+(top2-bottom2) - [max(top1,top2) - min(bottom1,bottom2)]
重叠长度为负数时面积为0
重叠面积overlapS=overlapX*overlapY

答案:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;

import java.lang.Math;
public class BlockedBillboard1 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("billboard.in"));
        PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("billboard.out")));
        int[][] rectangle = new int[3][4];
        int left, bottom, right, top;
        left = 0;
        bottom = 0;
        right = 0;
        top = 0;
        for (int i = 0; i < 3; ++i) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            left = Integer.parseInt(st.nextToken());
            rectangle[i][0]= left;
            bottom = Integer.parseInt(st.nextToken());
            rectangle[i][1]= bottom;
            right = Integer.parseInt(st.nextToken());
            rectangle[i][2]= right;
            top = Integer.parseInt(st.nextToken());

            rectangle[i][3]= top;
        }
        int overlapX, overlapY, overlapX2, overlapY2, sumOverLap, sumAllLap;
        overlapX = 0;
        overlapY = 0;
        overlapX2 = 0;
        overlapY2 = 0;
        sumOverLap = 0;
        sumAllLap = 0;
        overlapX = (rectangle[0][2]-rectangle[0][0])+(rectangle[2][2]-rectangle[2][0]) - (Math.max(rectangle[0][2],rectangle[2][2]) - Math.min(rectangle[0][0],rectangle[2][0]));
        overlapY = (rectangle[0][3]-rectangle[0][1])+(rectangle[2][3]-rectangle[2][1]) - (Math.max(rectangle[0][3],rectangle[2][3]) - Math.min(rectangle[0][1],rectangle[2][1]));
        overlapX = zero(overlapX);
        overlapY = zero(overlapY);
        overlapX2 = (rectangle[1][2]-rectangle[1][0])+(rectangle[2][2]-rectangle[2][0]) - (Math.max(rectangle[1][2],rectangle[2][2]) - Math.min(rectangle[1][0],rectangle[2][0]));
        overlapY2 = (rectangle[1][3]-rectangle[1][1])+(rectangle[2][3]-rectangle[2][1]) - (Math.max(rectangle[1][3],rectangle[2][3]) - Math.min(rectangle[1][1],rectangle[2][1]));
        overlapX2 = zero(overlapX2);
        overlapY2 = zero(overlapY2);
        sumOverLap = overlapX*overlapY + overlapX2*overlapY2;
        sumAllLap = (rectangle[0][2] - rectangle[0][0])*(rectangle[0][3] - rectangle[0][1]) + (rectangle[1][2] - rectangle[1][0])*(rectangle[1][3] - rectangle[1][1]);

        pw.println(sumAllLap - sumOverLap);
        br.close();
        pw.close();
    }
    private static int zero(int i) {
        if(i<0){
            return 0;
        }
        return i;
    }
}
<think>好的,我现在需要处理用户关于Java多线程编程的练习题和面试题的需求。首先,用户希望得到相关的问题或练习,可能是在准备面试或者想巩固多线程的知识。我需要根据提供的引用内容来生成相关的问题,同时确保问题覆盖多线程的不同方面,比如volatile关键字、线程池、死锁、ConcurrentHashMap等。 首先,查看用户提供的引用内容。引用[1]提到了volatile关键字的作用,包括可见性和禁止指令重排序,以及与CAS结合保证原子性。引用[2]是关于继承Thread类实现多线程的例子。引用[3]解释了线程池的核心线程处理任务机制。引用[4]讨论了死锁的诊断方法和ConcurrentHashMap。 接下来,我需要根据这些引用内容生成相关问题。比如,关于volatile的问题,可以问它的作用、与synchronized的区别、应用场景等。关于线程池,可以问工作原理、参数配置、拒绝策略等。死锁相关的问题可能涉及产生条件、诊断工具、避免方法。ConcurrentHashMap的问题可以包括线程安全实现、与HashTable的区别、1.7和1.8版本的差异等。 还要确保问题覆盖基础概念和实际应用,比如线程的创建方式、线程状态、锁机制、线程间通信、线程池的使用场景等。此外,可以加入一些需要代码实现的题目,如生产者消费者问题,或者使用特定类如CountDownLatch的示例。 需要注意的是,问题要有层次,从基础到进阶,覆盖理论知识和实际应用。同时,引用内容中的具体信息要正确对应到相关问题中,比如引用[4]提到的jps和jstack工具,可以生成关于死锁诊断的问题。 最后,整理问题,确保每个问题都有明确的考查点,并且与用户提供的引用内容相关联,同时符合常见的面试题或练习题模式。检查是否有重复或遗漏的重要知识点,如线程同步方法、并发集合类的使用、线程池参数配置等,确保问题全面且有针对性。</think>### Java多线程编程练习题与面试题整理 以下题目涵盖多线程核心概念、实际应用及常见陷阱,结合代码实践与理论分析,适合面试准备与技能提升。 --- #### **一、基础概念与线程创建** 1. **实现多线程的两种方式** - 编写代码分别通过`继承Thread类`和`实现Runnable接口`创建线程[^2],比较两者的优缺点。 ```java // 示例:继承Thread类 class MyThread extends Thread { private String whoAmI; private int delay; public MyThread(String name, int delay) { this.whoAmI = name; this.delay = delay; } @Override public void run() { try { Thread.sleep(delay); System.out.println(whoAmI + " 休眠 " + delay + "ms"); } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 2. **线程状态与生命周期** - 描述线程的`新建(NEW)`、`就绪(RUNNABLE)`、`运行(RUNNING)`、`阻塞(BLOCKED)`、`等待(WAITING)`、`超时等待(TIMED_WAITING)`、`终止(TERMINATED)`状态及转换条件。 --- #### **二、线程同步与锁机制** 3. **volatile关键字的作用** - 解释`volatile`如何保证可见性和禁止指令重排序[^1],举例说明其应用场景(如状态标志位)。 - 对比`volatile`与`synchronized`的异同。 4. **死锁的产生与诊断** - 编写一个会导致死锁的代码示例,并描述如何通过`jstack`或`jconsole`检测死锁[^4]。 ```java // 示例:死锁代码 Object lockA = new Object(); Object lockB = new Object(); new Thread(() -> { synchronized (lockA) { try { Thread.sleep(100); } catch (Exception e) {} synchronized (lockB) {} // 等待lockB } }).start(); new Thread(() -> { synchronized (lockB) { synchronized (lockA) {} // 等待lockA } }).start(); ``` --- #### **三、线程池与并发工具类** 5. **线程池的工作原理** - 解释线程池的`核心线程数`、`任务队列`、`最大线程数`、`拒绝策略`的作用[^3],画图说明任务提交流程。 6. **ConcurrentHashMap的线程安全实现** - 对比`ConcurrentHashMap`与`HashTable`的性能差异,解释其在JDK1.8中如何通过分段锁或CAS优化并发访问。 --- #### **四、高级应用与性能优化** 7. **生产者-消费者模型实现** - 使用`wait/notify`或`BlockingQueue`实现生产者-消费者模式,比较两种方式的优缺点。 8. **CAS与原子类** - 解释`CAS`(Compare And Swap)的原理,分析`AtomicInteger`在高并发场景下的性能优势。 --- #### **五、综合应用题** 9. **多线程统计文件词频** - 设计一个多线程程序,读取大型文本文件并统计单词频率,要求合理划分任务并合并结果。 10. **线程池参数调优** - 给定一个高并发Web服务器场景(如每秒处理1000个请求),如何配置线程池参数(核心线程数、队列容量等)?需考虑系统资源与响应时间平衡[^3]。 --- §§ 参考答案与扩展思考方向 §§ 1. **volatile的应用场景** - 状态标志位(如`while(!shutdown)`)、单例模式的双重检查锁定(需配合volatile禁止指令重排)。 2. **避免死锁的方法** - 加锁顺序一致、超时机制(如`tryLock`)、资源预分配。 3. **线程池拒绝策略选择** - `AbortPolicy`(直接抛异常)、`CallerRunsPolicy`(由提交线程执行任务)适用于不同业务场景[^3]。 4. **ConcurrentHashMap在JDK1.7与1.8的区别** - 1.7使用分段锁(Segment),1.8改为CAS + synchronized锁单个链表头节点。 --- 通过以上题目,可系统掌握多线程核心知识,建议结合代码实践与JVM工具(如jstack、VisualVM)深入分析线程行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值