UVa11595 Crossing Streets EXTREME

news2025/1/23 11:58:59

题目链接

         UVa11595 - Crossing Streets EXTREME

题意

        平面上有 n(n≤35)条直线,各代表一条街道。街道相互交叉,形成一些路段(对应于几何上的线段)。你的任务是设计一条从A到B的路线,使得穿过路段的拥挤值之和尽量小。为了安全,你的路线不能直接穿过街道的交叉点,也不能沿着街道走,而只能从路段的中间过街。
        平面上还有c(c≤1000)座大楼。正常情况下,每条路段的拥挤值为1,但如果和一座大楼相邻(即可以从这座大楼出发,不经过其他路段或者交叉点到达这条路段),拥挤值需要加上该大楼的拥挤度。

分析

        综合了平面区域分割和加权最短路的繁琐题目。

        本题解决平面区域分割采用“卷包裹”算法比切割多边形算法更合适。根据本题的数据特点,加权最短路用Dijkstra比SPFA更合适一点。

        说一些细节:

        1、区域的边界[-M,M],M取值多少合适?不要被题目诱导直接取1000,这其实是错的,取1000000也不严谨,应该取2e9

        2、区域的边界值很大,伴随而来的套平面几何算法模板的一些与0比较相关的函数eps需要调整,分析下来应该取1e-31e-4

        3、对每条线段(所有直线加上4条边界裁剪后变成线段)计算它与其他线段的交点,需要去重索引起来,后面分割出多边形也只用点的索引保存,这能为后续处理带来便利。

        4、卷包裹分割出各个多边形后,怎么高效判断多边形相邻(有公共边)?每个多边形的边,要么只属于它(在外边界),要么还属于另外一个多边形,可以用map<pair<int, int>, int> mp来记录关联。比如某个多边形x有边pair(u, v),则包含此边的另外一个多边形y = mp[pair(v, u)]。

        5、根据多边形相邻关系及多边形包含的大楼建加权图,对每个查询用Dijkstra求解。

        给一份测试数据。

        更多繁琐细节,参见AC代码。

AC代码

#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
using namespace std;

#define eps 1e-3
struct Point {
    double x, y;
    Point(double x = 0., double y = 0.): x(x), y(y) {}
};
typedef Point Vector;

Vector operator+ (const Vector& A, const Vector& B) {
    return Vector(A.x + B.x, A.y + B.y);
}

Vector operator- (const Vector& A, const Vector& B) {
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator* (const Vector& A, double p) {
    return Vector(A.x * p, A.y * p);
}

int dcmp(double x) {
    return abs(x) < eps ? 0 : (x < 0. ? -1 : 1);
}

bool operator== (const Point& a, const Point& b) {
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

double Cross(const Vector& A, const Vector& B) {
    return A.x * B.y - A.y * B.x;
}

double Dot(const Vector& A, const Vector& B) {
    return A.x * B.x + A.y * B.y;
}

double LineInterp(const Point& P, const Vector& v, const Point& Q, const Vector& w) {
    Vector u = P - Q;
    return Cross(w, u) / Cross(v, w);
}

#define M 2.1e9
#define N 42
struct node {
    int h, i;
    bool operator< (const node& rhs) const {
        return h > rhs.h;
    }
};
int g[N*N>>1][N<<1], t[N*N>>1], u[N*N>>1][N], e[N*N>>1], w[N*N>>1], h[N*N>>1], m, n, c, q, kase = 0;
Point p[N*N>>1], s[N]; Vector v[N], d[N*N>>1][N<<1]; double l[N], f[N]; bool vis[N*N>>1][N<<1];

int addPoint(const Point& x) {
    for (int i=0; i<n; ++i) if (p[i] == x) return i;
    p[n] = x;
    return n++;
}

void dfs(int x, int i, int s) {
    vis[x][i] = true;
    if (x == s) u[m][0] = s, e[m] = 1;
    int y = g[x][i];
    if (y != s) {
        u[m][e[m]++] = y;
        double c = 1., f; int z = -1;
        for (int j=0; j<t[y]; ++j)
            if (!vis[y][j] && Cross(d[x][i], d[y][j]) > 0. && (f = Dot(d[x][i], d[y][j])) < c) c = f, z = j;
        if (z >= 0) dfs(y, z, s);
        for (int j=0; j<t[y]; ++j) if (!vis[y][j]) dfs(y, j, y);
    } else u[m][e[m]] = s, w[m++] = 0;
}

int find(const Point& t) {
    for (int i=0, wn; i<m; ++i) {
        for (int j=wn=0; j<e[i]; ++j) {
            int k = dcmp(Cross(p[u[i][j+1]]-p[u[i][j]], t-p[u[i][j]]));
            int d1 = dcmp(p[u[i][j]].y - t.y);
            int d2 = dcmp(p[u[i][j+1]].y - t.y);
            if (k > 0 && d1 <= 0 && d2 > 0) wn++;
            if (k < 0 && d2 <= 0 && d1 > 0) wn--;
        }
        if (wn) return i;
    }
    return m;
}

void addW() {
    Point t; int c; cin >> t.x >> t.y >> c; w[find(t)] += c;
}

int query() {
    Point s, u; cin >> s.x >> s.y >> u.x >> u.y;
    int x = find(s), y = find(u);
    if (x == y) return 0;
    memset(h, 10, sizeof(h)); h[x] = 0;
    priority_queue<node> q; q.push({0, x});
    while (!q.empty()) {
        node z = q.top(); q.pop(); int i = z.i;
        if (i == y) return h[y];
        if (z.h > h[i]) continue;
        for (int j=0; j<t[i]; ++j) {
            int k = g[i][j], v = h[i] + w[i] + w[k] + 1;
            if (h[k] > v) h[k] = v, q.push({h[k], k});
        }
    }
    return h[y];
}

void solve() {
    m = 4;
    while (n--) {
        int a, b, c; cin >> a >> b >> c;
        if (a == 0) {
            if (abs(c) >= M*abs(b)) continue;
            s[m] = {-M, c/(double)-b}; v[m] = {1., 0.}; l[m++] = 2.*M;
        } else if (b == 0) {
            if (abs(c) >= M*abs(a)) continue;
            s[m] = {c/(double)-a, -M}; v[m] = {0., 1.}; l[m++] = 2.*M;
        } else {
            double d = sqrt(a*a + b*b); s[m] = {-M, (a*M-c)/b}; v[m] = {abs(b)/d, b>0 ? -a/d : a/d};
            f[0] = 0.; f[1] = Dot(Point(M, -(a*M+c)/b) - s[m], v[m]); f[2] = Dot(Point((b*M-c)/a, -M) - s[m], v[m]);
            f[3] = Dot(Point(-(b*M+c)/a, M) - s[m], v[m]); sort(f, f+4);
            p[1] = s[m] + v[m]*f[1]; p[2] = s[m] + v[m]*f[2];
            if (!dcmp(f[1]-f[2]) || dcmp(max(max(abs(p[1].x), abs(p[1].y)), max(abs(p[2].x), abs(p[2].y))) - M) > 0)
                continue;
            s[m] = p[1]; l[m++] = f[2] - f[1];
        }
    }
    memset(t, n = 0, sizeof(t));
    for (int i=0; i<m; ++i) {
        f[0] = 0.; f[1] = l[i]; Vector r(-v[i].x, -v[i].y); int c = 2;
        for (int j=0; j<m; ++j) if (dcmp(Cross(v[i], v[j]))) {
            double t = LineInterp(s[i], v[i], s[j], v[j]);
            if (t > 0. && t < l[i]) f[c++] = t;
        }
        sort(f, f+c); c = unique(f, f+c) - f;
        for (int j=1, a = addPoint(s[i]+v[i]*f[0]), b; j<c; a=b, ++j) {
            if (dcmp(f[j]-f[j-1]) == 0) {
                b = a; continue;
            }
            g[a][t[a]] = b = addPoint(s[i]+v[i]*f[j]), g[b][t[b]] = a, d[a][t[a]++] = v[i], d[b][t[b]++] = r;
        }
    }
    memset(vis, 0, sizeof(vis)); dfs(0, 0, m = 0);
    map<pair<int, int>, int> b;
    for (int i=0; i<m; ++i) for (int j=0; j<e[i]; ++j) b[pair<int, int>(u[i][j], u[i][j+1])] = i;
    for (int i=0; i<m; ++i) {
        for (int j=t[i]=0; j<e[i]; ++j) {
            pair<int, int> p(u[i][j+1], u[i][j]);
            if (b.count(p)) g[i][t[i]++] = b[p];
        }
        sort(g[i], g[i]+t[i]); t[i] = unique(g[i], g[i]+t[i]) - g[i];
    }
    while (c--) addW();
    cout << "Case " << ++kase << ':' << endl;
    while (q--) cout << query() << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    s[0] = s[3] = {-M, -M}; s[1] = {M, -M}; s[2] = {-M, M};
    v[0] = v[2] = {1., 0.}; v[1] = v[3] = {0., 1.}; l[0] = l[1] = l[2] = l[3] = 2.*M;
    while (cin >> n >> c >> q && n) solve();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1495401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用css结合js实现html文件中的双行混排

此前写过一个使用flex布局实现html文件中的双行混排&#xff0c;但是感觉效果不佳。经过几天思考&#xff0c;我认为双行混排的要点其实是两个&#xff1a; 1、正文和批注的文字大小不同&#xff1b; 2、正文和批注的行距相互配合进行设定。 正文和批注的文字大小及行距都可…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:TapGesture)

支持单击、双击和多次点击事件的识别。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 接口 TapGesture(value?: { count?: number, fingers?: number }) 参数&#xff1a; 参数名称参数类型必填参…

centos7 部署kibana

先决条件参考 虚拟机部署elasticsearch集群-CSDN博客 这里使用elk101服务器安装kibana 下载rpm包(这里添加了-c参数用到wget的断点续传功能) #下载kibana-rpm包以及校验文件 wget -c https://artifacts.elastic.co/downloads/kibana/kibana-7.17.18-x86_64.rpm wget -c htt…

小众问题 Debian 关机后马上自动启动,这是哪里出了问题?

环境&#xff1a;asrock华擎 2012年前后的桌面Mini Debian 12 作为局域网里的服务器用 这是一个特别小众的问题&#xff0c;因此也查不到相关资料&#xff0c;故特意保留在此&#xff0c;以备需要时查询。 问题&#xff1a;远程无论用什么方法都无法“真正”关机&#xff0c;…

水库大坝安全评价导则:大坝运行管理评价

一、一般规定 1、大坝运行管理评价的目的是&#xff0c;为安全鉴定提供大坝的运行、管理及性状等基础资料&#xff0c;作为大坝安全综合评价及分类的依据之一。 2、大坝运行管理评价的内容包括大坝运行、维修和监测。 3、大坝运行管理的各项工作应按相应的规范&#xff0c;结合…

RISC-V架构学习资料整理

1、韦东山——D1S哪吒开发板的裸机代码仓库 https://github.com/bigmagic123/d1-nezha-baremeta 2、melis系统移植到D1S https://blog.51cto.com/u_13800193/6268813 3、韦东山的gitee仓库 https://gitee.com/weidongshan 4、D1S编译工具链下载 https://github.com/Tina-Linux/…

SpringBoot集成图数据库neo4j实现简单的关联图谱

社交领域&#xff1a;Facebook, Twitter&#xff0c;Linkedin用它来管理社交关系&#xff0c;实现好友推荐 图数据库neo4j安装&#xff1a; 下载镜像&#xff1a;docker pull neo4j:3.5.0运行容器&#xff1a;docker run -d -p 7474:7474 -p 7687:7687 --name neo4j-3.5.0 ne…

进程间通信之信号灯 || 网络协议UDP/TCP || 三次握手四次挥手

在线程通信中由于数据段等内存空间的共用性&#xff0c;导致同时访问时资源竞争的问题&#xff0c;在线程中我们使用信号量的申请和释放&#xff0c;在防止资源竞争的产生。在进程间的通信中&#xff0c;有信号灯的概念。搭配共享内存实现进程同步。 有名信号量: 1.创建 …

数字创新的风口:创业者如何在Web3时代抢占先机

随着区块链技术的不断发展&#xff0c;Web3正成为数字创新的新风口&#xff0c;为创业者们带来了前所未有的机遇和挑战。本文将从另一个角度探讨Web3对创业者的影响&#xff0c;并提出创业者在Web3时代抢占先机的策略和方法。 1. Web3重新定义了商业模式 Web3不仅仅是一种技术…

安全测试报告-模板内容

1. 概述 为检验XXXX平台 系统的安全性&#xff0c;于 XXXX年 XX 月 XX 日至 XXXX年 XX 月 XX日对目标系统进行了安全测试。在此期间测试人员将使用各 种非破坏性质的攻击手段&#xff0c;对目标系统做深入的探测分析&#xff0c;进而挖掘系统中的安 全漏洞和风险隐患。研发团队…

论文翻译:一种基于强化学习的车辆队列控制策略,用于减少交通振荡中的能量消耗

A Reinforcement Learning-Based Vehicle Platoon Control Strategy for Reducing Energy Consumption in Traffic Oscillations 一种基于强化学习的车辆队列控制策略&#xff0c;用于减少交通振荡中的能量消耗 文章目录 A Reinforcement Learning-Based Vehicle Platoon Cont…

【Selenium】UI自动化|元素定位常见问题

1、报错NoSuchElementException——定位不到元素 分析的可能原因&#xff1a; 页面还没有加载出来&#xff0c;就对页面上的元素进行的操作 元素在iframe中&#xff0c;先要理解下frame的实质&#xff0c;frame中实际上是嵌入了另一个页面&#xff0c;而webdriver每次只能在一…

数仓之【MaxCompute】

一、简介 Maxcompute&#xff1a;云原生大数据计算服务是一种快速、完全托管的TB/PB级数据仓库解决方案。Maxcompute向用户提供了完善的数据导入方案以及多种经典的分布式计算模型&#xff0c;能够更快速的解决用户海量数据计算问题&#xff0c;有效降低企业成本&#xff0c;并…

单细胞联合BulkRNA分析思路|加个MR锦上添花,增强验证~

今天给大家分享一篇IF7.3的单细胞MR的文章&#xff0c;2023年12月发表在Frontiers in Immunology&#xff1a;An integrative analysis of single-cell and bulk transcriptome and bidirectional mendelian randomization analysis identified C1Q as a novel stimulated risk…

vue3学习(续篇)

vue3学习(续篇) 默认有vue3基础并有一定python编程经验。 chrome浏览器安装vue.js devtools拓展。 文章目录 vue3学习(续篇)1. element-ui使用2. axios 网络请求1. 简介2. 操作 3. flask-cors解决跨域问题1. 简介2. 操作 4. 前端路由 vue-router1. 简单使用2. 配置路径别名和…

LLM 应用的新兴架构

原文地址&#xff1a;emerging-architectures-for-llm-applications 大语言模型&#xff08;LLM&#xff09;为软件构建提供了一种强大的新方法。由于这种技术相对较新&#xff0c;且其运作方式与传统计算资源大相径庭&#xff0c;如何有效利用它们并不是显而易见的。 在这篇…

腾讯云4核8G服务器轻量和CVM可用来干什么?

腾讯云4核8G服务器适合做什么&#xff1f;搭建网站博客、企业官网、小程序、小游戏后端服务器、电商应用、云盘和图床等均可以&#xff0c;腾讯云4核8G服务器可以选择轻量应用服务器4核8G12M或云服务器CVM&#xff0c;轻量服务器和标准型CVM服务器性能是差不多的&#xff0c;轻…

Python报错ModuleNotFoundError: No module named ‘numpy‘

原因&#xff1a;缺少“numpy” 进入python安装路径&#xff0c;script路径内 在路径下启动终端 01.更新numpy python -m pip install --upgrade pip 02.安装 pip install numpy 03.运行python python 04.导入包 from numpy import * 问题已解决。

Python之Web开发初学者教程—初级教程成果下载

到目前为止&#xff0c;初级教程已经完成。 按照一步步的教程搭建虚拟机中的环境&#xff0c;包括内容如下&#xff1a; √ Ubuntu操作系统搭建 √ Python 配置 √ Redis 安装配置 √ Pycharm 安装配置 √ Python库中包括 √ Pip安装 √ Pyinstaller安装 √ Redis安装 √ Jieb…

vue3 setup函数与setup语法糖之间的区别

普通setup函数构建的组件 import {ref} from vueexport default {setup(){const countref(0)const handleUpdate()>{count.value}return{count,handleUpdate}}} </script>使用setup语法糖构建的组件 <script setup>import {ref} from vueconst countref(0)con…