算法:poj1066 宝藏猎人问题。

简介: package practice; import java.util.Scanner; public class TreasureHunt { public static void main(String[] args) { Scanner cin = new Scanner(System.
package practice;

import java.util.Scanner;

public class TreasureHunt {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int[][] walls;
        float x, y;
        int doors = Integer.MAX_VALUE, temp1, temp2;
        int n = cin.nextInt();
        walls = new int[n][4];
        for (int j = 0; j < n; j++) {
            walls[j][0] = cin.nextInt();
            walls[j][1] = cin.nextInt();
            walls[j][2] = cin.nextInt();
            walls[j][3] = cin.nextInt();
        }
        x = cin.nextFloat();
        y = cin.nextFloat();
        for (int j = 0; j < n; j++) {
            temp1 = find(walls[j][0], walls[j][1], x, y, walls, j);
            temp2 = find(walls[j][2], walls[j][3], x, y, walls, j);
            doors = temp1 < temp2 ? (temp1 < doors ? temp1 : doors)
                    : (temp2 < doors ? temp2 : doors);
        }
        if (n == 0)
            doors = 0;
        doors++;
        System.out.println("Number of doors = " + doors);
    }

    private static int find(int x1, int y2, float x, float y, int[][] walls,
            int j) {
        int count = 0;
        for (int i = 0, len = walls.length; i < len; i++) {
            if (i == j)
                continue;
            if (isIntersect(x1, y2, x, y, walls[i]))
                count++;
        }
        return count;
    }

    /**
     * 
     * 跨立实验
     */
    private static boolean isIntersect(int startX, int startY, float endX,
            float endY, int[] wall) {
        if ((Math.max(startX, endX) >= Math.min(wall[0], wall[2]))
                && (Math.max(wall[0], wall[2]) >= Math.min(startX, endX))
                && (Math.max(startY, endY) >= Math.min(wall[1], wall[3]))
                && (Math.max(wall[1], wall[3]) >= Math.min(startY, endY))
                && (multiply(wall[0], wall[1], endX, endY, startX, startY)
                        * multiply(endX, endY, wall[2], wall[3], startX, startY) > 0)
                && (multiply(startX, startY, wall[2], wall[3], wall[0], wall[1])
                        * multiply(wall[2], wall[3], endX, endY, wall[0],
                                wall[1]) > 0))
            return true;
        else
            return false;
    }

    private static double multiply(float x1, float y1, float x2, float y2,
            float x3, float y3) {
        return ((x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3));
    }

}
点我展开代码

该问题是:

一伙寻宝人探测到了埃及金字塔底层的宝藏,但是宝藏被n堵墙围着,如果要爆破,只能在每堵墙的中点开门。现在问题来了,对于随机给定的n堵墙,算出最少需要的开门数。

输入数据如下所示,第一行的整数n表示墙数,后面的n行表示墙体两端坐标,以金字塔边缘左下角为(0,0)右上角为(100,100),每行的四个数据分别为(x1,y1,x2,y2)

最后一行的数据表示宝藏点P的位置。

7
20 0 37 100
40 0 76 100
85 0 0 75
100 90 0 90
0 71 100 61
0 14 100 38
100 47 47 100
54.5 55.4

 

算法的思路很简单(但是实现有点儿问题,比较耗时,正在改进中):

用给出的所有点对宝藏点P做线段,找出交点最少的那一组,既是最小开门数。

 

以上结论需要证明多个推论,证明过程如下:

1、对于任意P,如果和P只间隔一堵墙,那么,P只需要开一扇门

证明:无需证明显而易见。

结论:只要证明墙数,就可以证明门数。

 

2、边缘上的任意一中点P0对P做线段,交点数等于P到Pi间隔的最小墙数

证明:

  连接P0-P,交点设为N。

  设,存在一条开门路径,连接P0到P,中间穿过了M堵墙。

  可知,P0-P与开门路径之间是封闭的多边形(路径是直线且与P0-P重合不讨论)。

  有定理一:最小完整路径不会两次闯过同一堵墙。(如果有两次闯过,则至少有三个交点A\B\C,连接A-C,则路径更少,易证)

  有定理二:两条子路径之间有且仅有一堵墙(易证,穿过墙只能抵达对侧,不能抵达同侧)

 

  由定理二可知,墙一定会经过多边形内部,由定理一可知,墙不会再次经过路径,则,墙一定会经过P0-P

  即是M<=N

 

  

  又有公理一:两条线段最多只有一个交点

  经过了P0-P的线段一定和封闭多边形相交。(由于线段端点落在金字塔边缘,易证)

  即N<=M

 

  所以M=N。

  

  

  

3、任意现存线段端点与P连线,交点数等于 邻近两个中点分别与P连线 的交点数 中的小值

证明:

  设有两线段L1,L2分别交金字塔外墙为P1,P2,且P1、P2之间再无其他现存线段的交点

  设有一点Pn处于P1,P2之间

  对Pn-P做连线,设有一现存直线Lx,与L1相交,但不与Pn-P相交,则此时满足Pn对P的交点数小于P1。

  此时,Lx与P1-P2外墙的交点,必然落在Pn和P1之间(此点易证),与P1、P2之间无现存线段交点违背。

  可证,Pn-P的交点数一定大于等于P1-P。

  同理可证Pn和P2关系。

 

  当等于的时候,Pn与P1等价。

  

  当大于的时候,推论如下:

  设有一点Px,Px在Pn-P1延长线上,为P1-P0(P0为另一相交点或者金字塔顶点,相交点等于顶点情况另行讨论)线段上的任意某点。

  

  可知,Px和P1之间再无任意交点。

  那么,沿用先前的推论,P1-P交点数大于等于Px-P0交点数。

  当大于的时候,必有一线段与P1-P相交,不与Px-P0相交,此线段不能落在P1-Px段,只能落在P1-Pn,且不为P1本身(相交非重合),与P1-Pn之间无交点违背。

  所以,必然是等于关系(同理可得L1即是Pn-P多出的那一相交线)

  

  相交点等于顶点情况,如果有P点同侧相交线,相交线必然与金字塔边缘有两个交点,无论落点如何,都能多次引用前半部分推论来同理证得。

  证毕。

 结论:

  只需要求线段端点与P的交点数,即可得到最小值。

   

 

目录
相关文章
|
8月前
|
人工智能 监控 Cloud Native
架构级拆解:AI数字人与数字员工的核心差异,玄晶引擎云原生实践启示
本文揭示AI数字人与AI数字员工的本质差异:前者仅为可视化交互组件,后者是具备业务闭环能力的云原生智能体。基于玄晶引擎与阿里云PAI实测,从架构、系统对接到弹性部署,解析如何实现“交互→决策→执行”全流程自动化,助力开发者精准选型,避免落地陷阱。
576 11
|
2天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1720 1
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
10天前
|
人工智能 JSON 安全
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
阿里云AI安全产品联动防御Fastjson攻击
2425 12
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
|
10天前
|
人工智能 自然语言处理 数据挖掘
Qwen3.8-Max-Preview深度全解析:2.4万亿参数旗舰MoE模型+Token Plan限时优惠完整落地指南
2026年7月,全新旗舰级混合专家大模型Qwen3.8-Max-Preview正式开放抢先体验,作为通义千问Qwen3系列规格最高、综合推理能力顶尖的新一代模型,该模型总参数量达到2.4万亿(2.4T),是当前线上可调用的原生多模态旗舰模型,综合推理水准对标海外顶级Fable 5模型,在复杂工程开发、长文档深度分析、多步骤智能体自治、跨境多语言创作、海量数据挖掘五大高难度业务场景实现跨越式性能提升。
1116 2
|
10天前
|
人工智能 自然语言处理 数据挖掘
最新版通义千问(Qwen3.8-Max-Preview)功能介绍
2026年,通义千问正式推出全新旗舰级大模型 **Qwen3.8-Max-Preview 预览版**,作为首款突破万亿参数规格的新一代基座模型,该模型总参数量达到**2.4万亿**,采用全新迭代的MoE混合专家架构,综合推理性能、长文本处理、多模态理解、复杂任务规划能力全面超越前代Qwen3.7-Max版本,整体实力跻身全球第一梯队,可对标海外顶级旗舰模型,是当前面向复杂工程开发、多智能体协同、超长文档解析、专业办公自动化场景的最优国产基座模型。
1163 0
|
12天前
|
人工智能
Qwen3.8抢先体验!正式版即将发布并开源!
千问Qwen3.8即将开源,参数达2.4T,进化速度以“天”计,实力媲美Fable 5。预览版Qwen3.8-Max已上线阿里Token Plan等平台,限时优惠:日间Credits低至1折,夜间更优,个人/团队版月付仅35元起!
1107 46
|
8天前
|
自然语言处理 测试技术 API
通义千问Qwen3.8-Max-Preview全功能解析:2.4万亿参数旗舰模型深度使用指南
在大模型技术持续迭代的当下,通义千问推出的Qwen3.8-Max-Preview作为新一代旗舰预览版模型,凭借2.4万亿参数的超大规模、多模态融合能力与全场景适配特性,成为开发者与企业用户探索AI应用的核心工具。该模型采用稀疏混合专家(MoE)架构,是通义千问首个突破万亿参数的多模态模型,可同时处理文本、图像、视频与文档等多种数据形态,在全栈代码开发、复杂逻辑推理、长文档分析与多智能体协作等场景实现跨越式升级。本文将全面拆解Qwen3.8-Max-Preview的核心功能,详解API调用流程与配置方法,覆盖多场景实战技巧,帮助用户快速掌握这款旗舰模型的使用方法,充分释放其性能潜力。
570 1
|
8天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
759 0