ZOJ 3537 Cake (凸包 + 区间DP && 最优三角形剖分)
题目链接:Here
题意:
给定 \(n\) 个点的坐标,先问这些点能否组成一个凸包,如是凸包,问用不相交的线来切这个凸包使得凸包只由三角形组成,根据 \(cost_{i, j} = |x_i + x_j| * |y_i + y_j| \% p\)算切线的费用,问最少的切割费用。
解题思路:参考于 ZeroClock,感谢!
经典的最优三角剖分模型加一点计算几何的知识。
先判断是否为凸包,这个排个序就好弄,搬了一下凸包函数排序的板子。
返回凸包中的顶点数量再与 \(n\) 比较。
这一步处理完之后就是用 \(n-3\) 条直线将凸包切成 \(n-2\) 个三角形。

我们要切的是以 \(1\) 和 \(n\) 为起始点的凸包,由于切线不能相交,那么选择 \(1\) 点和 \(n\) 点必有另外一点 \(S\) 要和它们组成一个三角形,然后凸包被分成三个部分: \(k_0,k_1,k_2\) ,然后把 \(k_1\) 看成一个以 \(n\) 点 \(S\) 点位起始点的凸包,是不是又可以用相同的方法处理这个凸包呢?答案是肯定,就是这样慢慢地将凸包分成一个个子凸包计算费用,最后再更新到点 \(1\) 和点 \(n\) 为起始点的凸包。
模拟上面的过程,设 \(Dp[i][j]\) 为以 \(i\) 为起点,\(j\) 为终点的凸包被切割成一个个小三角形所需要的费用。
那么
\]
为连一条 \(i\) 到 \(k\) 的线的费用),因为 \(dp[i][j]\) 只表示为以 \(i\) 为起点,\(j\) 为终点的凸包内部被切割的费用,所以在连线的时候可以加上边界费用而不算重复计算。
const int N = 1e3 + 10, inf = 1e9;
struct Point {
int x, y;
} p[N];
int cost[N][N], n, m;
int f[N][N];
int abs(int x) {return x < 0 ? -x : x;}
int xmul(Point p1, Point p2, Point p0) {
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
bool cmp(const Point &a, const Point &b) {
if (a.y == b.y)return a.x < b.x;
return a.y < b.y;
}
Point save[400], temp[400];
int Graham(Point *p, int n) {
sort(p, p + n, cmp);
save[0] = p[0];
save[1] = p[1];
int top = 1;
for (int i = 0; i < n; ++i) {
while (top && xmul(save[top], p[i], save[top - 1]) >= 0) top --;
save[++top] = p[i];
}
int mid = top;
for (int i = n - 2; i >= 0; --i) {
while (top > mid && xmul(save[top], p[i], save[top - 1]) >= 0) top --;
save[++top] = p[i];
}
return top;
}
int Count(Point a, Point b) {
return (abs(a.x + b.x) * abs(a.y + b.y)) % m;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
while (cin >> n >> m) {
for (int i = 0; i < n; ++i) cin >> p[i].x >> p[i].y;
int tot = Graham(p, n); // 求凸包
if (tot < n) {cout << "I can't cut.\n"; continue;}
memset(cost, 0, sizeof(cost));
// for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j)cost[i][j] = 0;
for (int i = 0; i < n; ++i)
for (int j = i + 2; j < n; ++j) cost[j][i] = cost[i][j] = Count(save[i], save[j]);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) f[i][j] = inf;
f[i][(i + 1) % n] = 0;
}
for (int i = n - 3; i >= 0; --i) // 注意三个for循环顺序
for (int j = i + 2; j < n; ++j) //因为要保证在算dp[i][j]时dp[i][k]和dp[k][j]时已经计算,所以i为逆序,j要升序
for (int k = i + 1; k <= j - 1; ++k)
f[i][j] = min(f[i][j], f[i][k] + f[k][j] + cost[i][k] + cost[k][j]);
cout << f[0][n - 1] << "\n";
}
}
ZOJ 3537 Cake (凸包 + 区间DP && 最优三角形剖分)的更多相关文章
- ZOJ - 3537 Cake (凸包+区间DP+最优三角剖分)
Description You want to hold a party. Here's a polygon-shaped cake on the table. You'd like to cut t ...
- ZOJ 3537 Cake (区间DP,三角形剖分)
题意: 给出平面直角坐标系上的n个点的坐标,表示一个多边形蛋糕,先判断是否是凸多边形,若否,输出"I can't cut.".若是,则对这个蛋糕进行3角形剖分,切n-3次变成n-2 ...
- ZOJ 3537 (凸包 + 区间DP)(UNFINISHED)
#include "Head.cpp" const int N = 10007; int n, m; struct Point{ int x,y; bool operator &l ...
- ZOJ 3537 Cake(凸包判定+区间DP)
Cake Time Limit: 1 Second Memory Limit: 32768 KB You want to hold a party. Here's a polygon-shaped c ...
- 区间DP Zoj 3537 Cake 区间DP 最优三角形剖分
下面是别人的解题报告的链接,讲解很详细,要注意细节的处理...以及为什么可以这样做 http://blog.csdn.net/woshi250hua/article/details/7824433 我 ...
- zoj 3537 Cake 区间DP (好题)
题意:切一个凸边行,如果不是凸包直接输出.然后输出最小代价的切割费用,把凸包都切割成三角形. 先判断是否是凸包,然后用三角形优化. dp[i][j]=min(dp[i][j],dp[i][k]+dp[ ...
- ZOJ 3537 Cake(凸包+区间DP)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537 题目大意:给出一些点表示多边形顶点的位置,如果不是凸多边形 ...
- ZOJ 3537 Cake 求凸包 区间DP
题意:给出一些点表示多边形顶点的位置(如果多边形是凹多边形就不能切),切多边形时每次只能在顶点和顶点间切,每切一次都有相应的代价.现在已经给出计算代价的公式,问把多边形切成最多个不相交三角形的最小代价 ...
- zoj 3537 Cake (凸包确定+间隔dp)
Cake Time Limit: 1 Second Memory Limit: 32768 KB You want to hold a party. Here's a polygon-sha ...
- ZOJ 3537 Cake
区间DP. 首先求凸包判断是否为凸多边形. 如果是凸多边形:假设现在要切割连续的一段点,最外面两个一定是要切一刀的,内部怎么切达到最优解就是求子区间最优解,因此可以区间DP. #include< ...
随机推荐
- 文心一言 VS 讯飞星火 VS chatgpt (145)-- 算法导论12.1 5题
五.用go语言,因为在基于比较的排序模型中,完成n个元素的排序,其最坏情况下需要 Ω(nlgn) 时间.试证明:任何基于比较的算法从 n 个元素的任意序列中构造一棵二又搜索树,其最坏情况下需要 Ω(n ...
- 【python】Tkinter学习
定义 python自带的可编辑的GUI界面,是一个图像窗口. Tkinter是使用python进行窗口视窗设计的模块. 标签-按钮 2.1.Lable&Button标签和按钮 定义window ...
- 黑客玩具入门——2、Kali常用命令与简单工具
一.Linux常用命令 首先,我们启动kali系统,然后点击这里的命令行工具. 就可以使用下面学习的命令了,另外,如果你有过计算机基础,那么Mac的terminal和Git的gitbash,都是可以练 ...
- 2023年的PHP项目部署笔记。什么?还有人用PHP?
前言 这是我第一次用 PHP 的包管理工具 composer 一开始用 docker 进行部署,但一直出问题,最后还是选择直接在服务器上安装 php-fpm 搭配 nginx 的方案了. PS:doc ...
- c标签的使用问题
这是在使用c标签的时候遇到的问题,发现在导入包成功的情况下,jsp页面代码也没有问题.在网页上查了查,发现需要修改tomcat中的 conf/catalina.properties文件. 将tomca ...
- 安卓之各种Adapter优劣分析
文章摘要 在 Android 开发中,适配器(Adapter)是一种非常重要的设计模式,它用于将数据与视图组件进行绑定.适配器可以帮助我们在不同的视图组件(如 ListView.GridView.Re ...
- Selenium-ActionChains动作链(针对鼠标、滚轮等操作
https://www.selenium.dev/documentation/webdriver/actions_api/ 注意:对于滚轮的操作,只支持chrome浏览器,且selenium版本在4. ...
- Asp.net core Webapi 项目如何优雅地使用内存缓存
前言 缓存是提升程序性能必不可少的方法,Asp.net core 支持多级缓存配置,主要有客户端缓存.服务器端缓存,内存缓存和分布式缓存等.其中客户端缓和服务器端缓存在使用上都有比较大的限制,而内存缓 ...
- 自定义md-loader来简单高效的维护组件文档
个人觉得,组件库最难的不是开发,而是使用,怎么才能让组内同事都用起来,这才是关键 背景 虽然现在开源的组件库很多,但每个项目里还是或多或少都会有人封装出一些项目内通用的基础组件.业务组件 我参与过多个 ...
- 如何从零开始实现TDOA技术的 UWB 精确定位系统(2)
这是一个系列文章<如何从零开始实现TDOA技术的 UWB 精确定位系统>第2部分. 重要提示(劝退说明): Q:做这个定位系统需要基础么?A:文章不是写给小白看的,需要有电子技术和软件编程 ...