ZOJ 3537 Cake 【区间DP + 凸多边形三角剖分】

news2024/11/18 4:29:41

Cake

1

题意

给定平面坐标上的 n n n 个点,如果是凸多边形的话,就用最少的花费把这个多边形剖分成若干个三角形,剖分的线段端点只能是原多边形的顶点,一条线段的花费为: ∣ x i + x j ∣ × ∣ y i + y j ∣ m o d p |x_i + x_j| \times |y _i + y_j| mod p xi+xj×yi+yjmodp

思路

首先我们使用 A n d r e w Andrew Andrew 算法判断一下是否为凸包。对于当前的顶点 [ 0 , n − 1 ] [0, n - 1] [0,n1],我们先看一条边: 0 ↔ n − 1 0 \lrarr n - 1 0n1,这条边肯定属于某个三角形,我们肯定要有一条线的端点之一是 0 0 0,另外一条线的端点之一是 n − 1 n - 1 n1,并且这两条线有一个公共端点 k ( 1 ≤ k ≤ n − 2 ) k(1 \leq k \leq n - 2) k(1kn2),因为只有这样,才能将这条边剖分成属于某个三角形,而那两条线段就是三角形的两条边,第三条边就是 0 ↔ n − 1 0 \lrarr n - 1 0n1

那么这两条线就将我们的 [ 0 , n − 1 ] [0, n - 1] [0,n1] 区间的端点分成了两个部分: [ 0 , k ] [0, k] [0,k] [ k + 1 , n − 1 ] [k + 1, n - 1] [k+1,n1],这是两个子状态,我们可以使用 d p [ l ] [ r ] dp[l][r] dp[l][r] 表示区间 [ l , r ] [l,r] [l,r] 的三角剖分的最小花费

那么转移就可以枚举区间的分裂点 k k k

  • d p [ l ] [ k ] = m i n l + 1 ≤ k ≤ r − 1 ( d p [ l ] [ k ] + d p [ k + 1 ] [ r ] + c o s t ( l , k ) + c o s t ( k , r ) ) dp[l][k] = min_{l + 1 \leq k \leq r - 1} (dp[l][k] + dp[k + 1][r] + cost(l, k) + cost(k, r)) dp[l][k]=minl+1kr1(dp[l][k]+dp[k+1][r]+cost(l,k)+cost(k,r)) c o s t ( l , k ) cost(l,k) cost(l,k) 表示连接 l l l k k k 的花费

注意如果 l + 1 ≤ r l + 1 \leq r l+1r 时, c o s t ( l , r ) = 0 cost(l, r) = 0 cost(l,r)=0,因为原本的多边形上已经有了这条边,不用而外花费去切割

跑区间 D P DP DP 的时候,我们从长度为 3 3 3 的区间开始,长度小于等于 2 2 2 的区间花费都为 0 0 0,都不用切割

时间复杂度: O ( n 3 ) O(n^3) O(n3)

#include<bits/stdc++.h>
#define fore(i,l,r)	for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;

const int INF=0x3f3f3f3f;
const long long INFLL=1e18;

typedef long long ll;

int mod;

struct Point{
    int x,y;

    Point(int xx=0,int yy=0){x=xx,y=yy;}

    Point operator + (Point B){ //向量 +
        return Point(x+B.x,y+B.y);
    }
	
    Point operator - (Point B){	//向量 -
        return Point(x-B.x,y-B.y);
    }

    Point operator * (int k){ //向量等比例放大
        return Point(k*x,k*y);
    }
    bool operator == (Point B){ //unique 用到
        return x-B.x == 0 && y-B.y == 0;
    }

    bool operator < (Point B){
        return x-B.x < 0 || (x-B.x == 0 && y-B.y < 0);
    }
};

int Cross(Point A,Point B){
    return A.x*B.y - A.y*B.x;
}

int Convex_hull(Point* p,int n,Point* ch){ //ch[]储存凸包顶点
    n = std::unique(p,p+n) - p;	//去重
    std::sort(p,p+n); //排序
    int v = 0;
    /* 求下凸包 */
    fore(i,0,n){
        while(v>1 && Cross(ch[v-1]-ch[v-2],p[i]-ch[v-2]) <= 0)
            --v;
        ch[v++] = p[i];
    }
    int j = v;
    /* 求上凸包 */
    for(int i=n-2;i>=0;--i){
        while(v>j && Cross(ch[v-1]-ch[v-2],p[i]-ch[v-2]) <= 0)
            --v;
        ch[v++] = p[i];
    }
    if(n>1)	--v; //p[0]被加入了两次
    return v; //返回凸包顶点数
}

Point p[500];
Point ch[500];

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int n;
    while(std::cin >> n >> mod){
        fore(i, 0, n) std::cin >> p[i].x >> p[i].y;
        
        if(Convex_hull(p, n, ch) < n){ //不是凸包
            std::cout << "I can't cut.\n";
            continue;
        }

        if(n <= 3){
            std::cout << "0\n";
            continue;
        }

        std::vector<std::vector<int>> dp(n + 5, std::vector<int>(n + 5, INF));
        std::vector<std::vector<int>> dis(n + 5, std::vector<int>(n + 5, 0)); //连接两个顶点的cost

        auto cal = [&](int i, int j) { //计算cost
            return std::abs(ch[i].x + ch[j].x) * std::abs(ch[i].y + ch[j].y) % mod;
        };

        fore(i, 0, n)
            fore(j, i + 2, n)
                dis[i][j] = dis[j][i] = cal(i, j); //预计算cost
        
        fore(i, 0, n) dp[i][i + 1] = 0;
        
        fore(len, 3, n + 1)
            fore(L, 0, n - len + 1){
                int R = L + len - 1;
                fore(k, L + 1, R)
                    dp[L][R] = std::min(dp[L][R], dp[L][k] + dp[k][R] + dis[L][k] + dis[k][R]);
            }
        std::cout << dp[0][n - 1] << endl;
    }
    return 0;
}

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

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

相关文章

微信小程序开发学习笔记《16》uni-app框架

微信小程序开发学习笔记《16》uni-app框架 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读uni-app对应官方文档 一、uni-app简介 **uni-app是一个使用Vue.js 开发所有前端应用的框架。**开发者编写一套代码&#xff…

70.SpringMVC怎么和AJAX相互调用的?

70.SpringMVC怎么和AJAX相互调用的&#xff1f; &#xff08;1&#xff09;加入Jackson.jar&#xff08;2&#xff09;在配置文件中配置json的消息转换器.(jackson不需要该配置HttpMessageConverter&#xff09; <!‐‐它就帮我们配置了默认json映射‐‐> <mvc:anno…

NTLM||LM算法lsasswinlogon进程

来填坑了&#xff0c;这篇blog我们就来讲一下mimikatz能抓到开机的密码的原理 1.lsass&&winlogon 不知道大家有没有好奇过&#xff0c;我们每次开机输入密码之后&#xff0c;电脑又怎么知道我们是否输入正确呢&#xff1f; &#xff1a;这就要的得益于我们的两个进程…

【前后端的那些事】webrtc入门demo(代码)

文章目录 前端代码apivue界面 后端modelwebsocketconfigresource 龙年到了&#xff0c;先祝福各位龙年快乐&#xff0c;事业有成&#xff01; 最近在搞webrtc&#xff0c;想到【前后端的那些事】好久都没有更新了&#xff0c;所以打算先把最近编写的小demo发出来。 p2p webrt…

Android 移动应用开发 创建第一个Android项目

文章目录 一、创建第一个Android项目1.1 准备好Android Studio1.2 运行程序1.3 程序结构是什么app下的结构res - 子目录&#xff08;所有图片、布局、字AndroidManifest.xml 有四大组件&#xff0c;程序添加权限声明 Project下的结构 二、开发android时&#xff0c;部分库下载异…

【Dubbo源码二:Dubbo服务导出】

入口 Dubbo服务导出的入口&#xff1a;服务导出是在DubboBootstrapApplicationListener在监听到ApplicationContextEvent的ContextRefreshedEvent事件后&#xff0c;会触发dubboBootstrap.start(), 在这个方法中最后会导出Dubbo服务 DubboBootstrapApplicationListener Dub…

【北邮鲁鹏老师计算机视觉课程笔记】03 edge 边缘检测

【北邮鲁鹏老师计算机视觉课程笔记】03 1 边缘检测 有几种边缘&#xff1f; ①实体上的边缘 ②深度上的边缘 ③符号的边缘 ④阴影产生的边缘 不同任务关注的边缘不一样 2 边缘的性质 边缘在信号突变的地方 在数学上如何寻找信号突变的地方&#xff1f;导数 用近似的方法 可以…

【DDD】学习笔记-领域模型与函数范式

函数范式 REA 的 Ken Scambler 认为函数范式的主要特征为&#xff1a;模块化&#xff08;Modularity&#xff09;、抽象化&#xff08;Abstraction&#xff09;和可组合&#xff08;Composability&#xff09;&#xff0c;这三个特征可以帮助我们编写简单的程序。 通常&#…

电商网站基础布局——以小兔鲜为例

项目准备 /* base.css */ /* 內减模式 */ * {margin: 0;padding: 0;box-sizing: border-box; }/* 设置网页统一的字体大小、行高、字体系列相关属性 */ body {font: 16px/1.5 "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei","Hiragino Sans…

编码安全风险是什么,如何进行有效的防护

2011年6月28日晚20时左右&#xff0c;新浪微博突然爆发XSS&#xff0c;大批用户中招&#xff0c;被XSS攻击的用户点击恶意链接后并自动关注一位名为HELLOSAMY的用户&#xff0c;之后开始自动转发微博和私信好友来继续传播恶意地址。不少认证用户中招&#xff0c;也导致该XSS被更…

【深蓝学院】移动机器人运动规划--第4章 动力学约束下的运动规划--笔记

0. Outline 1. Introduction 什么是kinodynamic&#xff1f; 运动学&#xff08;Kinematics&#xff09;和动力学&#xff08;Dynamics&#xff09;都是力学的分支&#xff0c;涉及物体的运动&#xff0c;但它们研究的焦点不同。 运动学专注于描述物体的运动&#xff0c;而…

反应式编程

反应式编程 前言1 反应式编程概览2 初识 Reactor2.1 绘制反应式流图2.2 添加 Reactor 依赖 3.使用常见的反应式操作3.1 创建反应式类型3.2 组合反应式类型3.3 转换和过滤反应式流3.4 在反应式类型上执行逻辑操作 总结 前言 你有过订阅报纸或者杂志的经历吗?互联网的确从传统的…

第66讲管理员登录功能实现

项目样式初始化 放assets目录下&#xff1b; border.css charset "utf-8"; .border, .border-top, .border-right, .border-bottom, .border-left, .border-topbottom, .border-rightleft, .border-topleft, .border-rightbottom, .border-topright, .border-botto…

WWW 万维网

万维网概述 万维网 WWW (World Wide Web) 并非某种特殊的计算机网络。 万维网是一个大规模的、联机式的信息储藏所。 万维网用链接的方法能非常方便地从互联网上的一个站点访问另一个站点&#xff0c;从而主动地按需获取丰富的信息。 这种访问方式称为“链接”。 万维网是分…

线上编程答疑解惑回顾,初学编程中文编程在线屏幕共享演示

线上编程答疑解惑回顾&#xff0c;初学编程中文编程在线屏幕共享演示 一、学编程过程中有不懂的怎么办&#xff1f; 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——常用工具下载——编…

Python入门知识点分享——(二十)继承和方法重写

今天是大年三十&#xff0c;祝大家龙年大吉&#xff0c;当然无论何时何地&#xff0c;我们都不要忘记继续学习。今天介绍的是继承和方法重写这两种面向对象编程特点。继承机制指的是&#xff0c;一个类&#xff08;我们称其为子类或派生类&#xff09;可以使用另一个类&#xf…

无心剑中译佚名《春回大地》

The Coming of Spring 春回大地 I am coming, little maiden, With the pleasant sunshine laden, With the honey for the bee, With the blossom for the tree. 我来啦&#xff0c;小姑娘 满载着欣悦的阳光 蜂儿有蜜酿 树儿有花绽放 Every little stream is bright, All …

【Leetcode】LCP 30. 魔塔游戏

文章目录 题目思路代码结果 题目 题目链接 小扣当前位于魔塔游戏第一层&#xff0c;共有 N 个房间&#xff0c;编号为 0 ~ N-1。每个房间的补血道具/怪物对于血量影响记于数组 nums&#xff0c;其中正数表示道具补血数值&#xff0c;即血量增加对应数值&#xff1b;负数表示怪…

Apache Zeppelin 整合 Spark 和 Hudi

一 环境信息 1.1 组件版本 组件版本Spark3.2.3Hudi0.14.0Zeppelin0.11.0-SNAPSHOT 1.2 环境准备 Zeppelin 整合 Spark 参考&#xff1a;Apache Zeppelin 一文打尽Hudi0.14.0编译参考&#xff1a;Hudi0.14.0 最新编译 二 整合 Spark 和 Hudi 2.1 配置 %spark.confSPARK_H…

moduleID的使用

整个平台上有很多相同的功能&#xff0c;但是需要不同的内容。例如各个模块自己的首页上有滚动新闻、有友好链接等等。为了公用这些功能&#xff0c;平台引入了moduleID的解决方案。 在前端的配置文件中&#xff0c;配置了模块号&#xff1a; 前端页面请求滚动新闻时&#xff0…