Task Planine 计算几何 凸包

本文介绍了一道涉及计算几何和贪心算法的题目,通过对凸包的理解和应用,实现了一个有效的解决方案。主要内容包括:利用计算几何的基础函数,对凸包进行处理,找到覆盖每个山谷所需的最少光源数量。

Task Planine

题意

给一座山脉的二维坐标系模型,以轮廓的坐标点来表示,求最少几个光源可以覆盖每一个山谷。

思路

有一些前置知识是,计算几何的基本函数编写,对凸包有一定的理解。

容易想到把所有的谷映射到h高度的一些区间,对区间做贪心的算法。

这里就是我用一个segs存所有区间的边界点,tag标志左右,id表示第几个区间,x表示位置。

int dcmp(double x) {
    if (fabs(x) < EPS) return 0;
    return x < 0 ? -1 : 1;
}

struct Seg {
    double x;
    int tag; // l:0, r:1
    int id;

    bool operator<(const Seg &r) const {
        if (dcmp(x - r.x) == 0) return tag < r.tag;
        return dcmp(x - r.x) < 0;
    }
};

Seg segs[MAXN];
int vis[MAXN]; // 0: unvis, 1: wip
int stk[MAXN], stk_top;

贪心的思路就是,每次枚举到右边界,就清算之前所有的左边界,记一次答案,并且标记为已经点亮。

{
	int ans = 0;

    for (int i = 1; i <= segs_cnt; ++i) {
        const Seg &s = segs[i];
        if (s.tag == 0) {
            stk[++stk_top] = s.id;
        } else {
            if (vis[s.id]) continue;
            ans++;
            while (stk_top) {
                vis[stk[stk_top--]] = 1;
            }
        }
    }
}

下面的问题就是如何投射这些区间。

在这里插入图片描述

通过观察一些比较极端的样例,可以发现,所有的区间夹角都在相邻的凸包边上。随着上凸包的不断更新,在对应的点就可以找到边界无遮挡的射线。

下面的唯一的难点就在于一边计算上图包,一边计算每个谷投射区间边界的射线。

{
	hull[1] = p[1];
    hull[2] = p[2];
    hull_cnt = 2;

    int segs_cnt = 0;
    for (int j = 3; j < n; j++) {
        while (hull_cnt > 2 && Cross(hull[hull_cnt] - hull[hull_cnt - 1], p[j] - hull[hull_cnt - 1]) > 0)
            hull_cnt--;

        hull[++hull_cnt] = p[j];

        if (1 < j && j < n && j % 2 == 1) {
            double x = getx(hull[hull_cnt - 1], hull[hull_cnt], h);
            segs[++segs_cnt] = {x, 0, j / 2};
        }
    }
}

对凸包有理解话,实际上和凸包有关的核心代码只有那个while,我使用的是Graham扫描的算法原理。这个while在不断的维护顺时针的上凸包。这片代码在插入所有谷投射的左边界。

下一个for是在求右边界,但是因为顺序是反着的,代码顺序有一些细节,先学过凸包可以慢慢推理。

完整代码

/**
  *    █████╗  ██████╗       ██████╗ ██╗     ███████╗
  *   ██╔══██╗██╔════╝       ██╔══██╗██║     ╚══███╔╝
  *   ███████║██║            ██████╔╝██║       ███╔╝
  *   ██╔══██║██║            ██╔═══╝ ██║      ███╔╝
  *   ██║  ██║╚██████╗▄█╗    ██║     ███████╗███████╗
  *   ╚═╝  ╚═╝ ╚═════╝╚═╝    ╚═╝     ╚══════╝╚══════╝
  *
  *  @Author: TieWay59
  *  @Created: 2021/3/20 19:48
  *  @Link: http://10.7.95.2/CLanguage/contests/1181/problems/1010.html
  *  @Tags:
  *
  *******************************************************/

#include <bits/stdc++.h>

#ifdef DEBUG

#   include "libs59/debugers.h"
//  #define debug(x)  cerr <<#x << " = "<<x<<endl;
#else
#   define endl '\n'
#   define debug(...)
#   define max(x,y) ((x)>(y)?(x):(y))
#   define min(x,y) ((x)>(y)?(y):(x))
#endif

#define STOPSYNC ios::sync_with_stdio(false);cin.tie(nullptr)
#define MULTIKASE int Kase=0;cin>>Kase;for(int kase=1;kase<=Kase;kase++)
typedef long long ll;
const int MAXN = 1e6 + 59;
const int MOD = 1e9 + 7;
const int INF = 0x3F3F3F3F;
const ll llINF = 0x3F3F3F3F3F3F3F3F;
using namespace std;
using pii = pair<int, int>;
using vint = vector<int>;
const double EPS = 1e-8;

int dcmp(double x) {
    if (fabs(x) < EPS) return 0;
    return x < 0 ? -1 : 1;
}

struct Point {
    double x, y;
};

Point p[MAXN];
Point hull[MAXN];
int hull_cnt;

inline double Cross(Point a, Point b) {
    return a.x * b.y - a.y * b.x;
}

inline Point operator-(Point a, Point b) {
    return Point{a.x - b.x, a.y - b.y};
}

double getx(const Point &a, const Point &b, double h) {
    return (h - a.y) / (b.y - a.y) * (b.x - a.x) + a.x;
}

struct Seg {
    double x;
    int tag; // l:0, r:1
    int id;

    bool operator<(const Seg &r) const {
        if (dcmp(x - r.x) == 0) return tag < r.tag;
        return dcmp(x - r.x) < 0;
    }
};

Seg segs[MAXN];
int vis[MAXN]; // 0: unvis, 1: wip
int stk[MAXN], stk_top;

void solve(int kaseId = -1) {
    int n, h; // n is odd

    cin >> n >> h;

    for (int i = 1, x, y; i <= n; ++i) {
        cin >> x >> y;
        p[i] = {double(x), double(y)};
    }

    if (n == 3) {
        cout << 0 << endl;
        return;
    }
    
    hull[1] = p[1];
    hull[2] = p[2];
    hull_cnt = 2;

    int segs_cnt = 0;
    for (int j = 3; j < n; j++) {
        while (hull_cnt > 2 && Cross(hull[hull_cnt] - hull[hull_cnt - 1], p[j] - hull[hull_cnt - 1]) > 0)
            hull_cnt--;

        hull[++hull_cnt] = p[j];

        if (1 < j && j < n && j % 2 == 1) {
            double x = getx(hull[hull_cnt - 1], hull[hull_cnt], h);
            segs[++segs_cnt] = {x, 0, j / 2};
        }
    }

    hull[1] = p[n];
    hull[2] = p[n - 1];
    hull_cnt = 2;

    for (int j = n - 2; j > 1; j--) {
        while (hull_cnt > 2 && Cross(hull[hull_cnt - 1] - p[j], hull[hull_cnt - 1] - hull[hull_cnt]) > 0)
            hull_cnt--;

        hull[++hull_cnt] = p[j];

        if (1 < j && j < n && j % 2 == 1) {
            double x = getx(hull[hull_cnt - 1], hull[hull_cnt], h);
            segs[++segs_cnt] = {x, 1, j / 2};
        }
    }
    
    sort(segs + 1, segs + 1 + segs_cnt);

    int ans = 0;

    for (int i = 1; i <= segs_cnt; ++i) {
        const Seg &s = segs[i];
        if (s.tag == 0) {
            stk[++stk_top] = s.id;
        } else {
            if (vis[s.id]) continue;
            ans++;
            while (stk_top) {
                vis[stk[stk_top--]] = 1;
            }
        }
    }

    cout << ans << endl;
}

void solves() {
    MULTIKASE {
        solve(kase);
    }
}

int main() {
#ifdef DEBUG
    freopen("input.txt", "r+", stdin);
#endif
    STOPSYNC;
    solve();
    return 0;
}
/*

 */
内容概要:本文聚焦于不计电池储能寿命损耗的微电网经济调度问题,提出了一种融合电价型、激励型及可中断负荷型三类需求侧响应机制的优化调度模型。研究基于Matlab平台构建了包含光伏、风机、储能系统等多种分布式能源的微电网运行成本最小化模型,详细阐述了目标函数与约束条件的数学建模过程,并通过仿真验证了所提策略在降低系统运行成本、实现削峰填谷和提升能源利用效率方面的有效性。该模型强调需求侧资源的灵活调控能力,为微电网的经济高效运行提供了理论支持和技术路径。; 适合人群:电力系统、能源互联网及相关专业的高校研究生、科研人员,以及从事微电网优化调度、综合能源系统规划与运行的工程技术人员。; 使用场景及目标:①用于教学科研中深入理解微电网经济调度的核心原理、建模方法与求解流程;②为实际微电网项目中整合多类型需求侧响应资源、制定优化运行策略提供可复现的仿真工具与技术参考;③作为进一步研究更复杂场景(如计入储能寿命损耗、碳排放约束、不确定性因素等)的优化模型的基础框架。; 阅读建议:读者应具备电力系统基础理论知识和Matlab编程能力,建议结合文中模型逐步复现代码,通过调整负荷曲线、能源价格、响应参数等变量进行敏感性分析,以深化对调度机制的理解。需特别注意,本模型未考虑电池寿命损耗这一关键因素,在实际工程应用中应结合电池老化模型进行补充和完善,以获得更贴近现实的调度方案。
内容概要:本文提出了一种考虑阶梯式碳交易与供需灵活双响应的综合能源系统优化调度模型,并通过Matlab代码实现。该模型深度融合了阶梯式碳交易机制与电力系统中需求侧及供给侧的灵活响应能力,构建了一个涵盖电、热、气等多种能源形式耦合的综合能源系统框架。通过引入阶梯碳价机制,有效激励系统低碳运行,同时结合需求响应与供给调整的协同优化策略,显著提升了系统运行的经济性与环保性。研究采用先进的数学优化方法对模型进行求解,实现了对系统内各能源单元出力、储能设备调度、负荷转移等关键变量的全局最优配置,为实现能源高效利用与碳排放最小化的双重目标提供了科学支撑。; 适合人群:具备电力系统、能源系统建模或优化调度等相关背景的科研人员与工程技术人员,特别适合从事综合能源系统规划、低碳调度策略、碳交易机制设计等方向研究的研究生及高校教师。; 使用场景及目标:①深入研究阶梯式碳交易机制在综合能源系统中的建模方法与应用效果;②实现供需双侧灵活互动下的系统经济性与低碳化协同优化调度;③为区域能源系统的低碳转型提供量化分析工具与决策支持依据;④作为Matlab平台下能源系统优化建模的教学案例或科研复现参考。; 阅读建议:建议读者结合提供的Matlab代码逐行解析模型构建过程,重点掌握目标函数与约束条件的数学建模逻辑及其程序实现方式。在学习过程中应积极尝试调整碳价阶梯参数、改变负荷响应场景以观察系统优化结果的变化,从而深化对模型机理的理解。同时,可将本模型与单一碳价或其他需求响应模型进行对比分析,进一步拓展研究视野与创新思路。
已经博主授权,源码转载自 https://pan.quark.cn/s/43c3d5a5f28a 在Web开发领域中,网站系统升级维护提示页面的构建与部署占据着至关重要的地位,特别是在系统进行更新操作或进行故障修复期间,为了确保用户操作的流畅性和数据的完整性,通常会运用到此类提示界面。一个名为"网站系统升级维护提示页面.rar"的归档文件内,收录了完成这一功能所必需的核心构成部分。其中,`index.html`文件作为网页的核心载体,负责构建页面的基本框架和呈现内容。针对当前的应用情境,`index.html`文件极有可能运用一种简约而雅致的布局设计,用以呈现"系统升级维护中"的状态信息。编程人员能够在这个文档中定位到展示企业标识和建设性升级提示的代码单元,并且可以依据实际需求进行个性化设置。 `css`目录中存放的是CSS(层叠样式表)文档,这些文档负责设定页面的视觉表现,涵盖色彩搭配、字体选用、页面布局以及响应式设计等多个方面。在系统升级维护的提示页面上,CSS样式或许已经预设了与整体风格相契合的色彩搭配和元素排布,以此保障页面的视觉吸引力和专业性。编程人员可以通过调整这些样式规范来优化页面的整体观感,使其与企业的品牌形象保持一致。 `images`目录则用于存储页面装饰或信息传递所需的图形素材。这些图形可能包含加载指示器、公司标识以及其他与系统升级维护相关的视觉符号。图形素材的挑选和设计对于信息的有效传递以及用户体验的提升具有决定性作用。编程人员可以根据实际需求进行图形素材的替换或增补,确保其与整体页面设计风格相吻合。 `js`目录内包含了JavaScript程序代码,这些代码负责处理页面的交互机制和动态表现。例如,JavaScript代码可能被用于实现计时功能,显...
内容概要:本文针对计及碳排放的多微网电能交互问题,提出了一种基于交替方向乘子法(ADMM)的分布式运行优化策略。通过构建包含可再生能源、储能系统、可控负荷及碳交易机制的多微网协同优化模型,实现了在去中心化架构下各微电网的独立决策与全局协同优化。研究充分考虑碳排放约束,利用ADMM算法将集中式优化问题分解为多个子问题并行求解,有效提升了计算效率与系统可扩展性。通过Matlab平台进行仿真验证,结果表明该策略不仅能降低系统综合运行成本,还能显著提高清洁能源消纳水平并减少碳排放,为构建低碳、高效、自治的多微网能源系统提供了可行的技术路径。; 适合人群:电力系统、综合能源系统、能源互联网等领域的高校研究生、科研人员及工程技术人员,尤其适合具备优化算法理论基础和Matlab编程能力的专业人士。; 使用场景及目标:①应用于多微电网系统的分布式能量管理与协同调度;②支持碳交易机制下的低碳运行优化设计与政策仿真;③为ADMM等分布式优化算法在能源系统中的工程化应用提供可复现的代码实例与方法论指导。; 阅读建议:建议结合提供的Matlab代码深入理解算法实现细节,重点掌握ADMM的变量分裂、增广拉格朗日函数构建及收敛判据设置,同时可进一步拓展至不同通信拓扑或不确定性场景下的鲁棒性分析,以全面提升对分布式能源系统协同优化的认知与实践能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值