UVa1483/LA5075 Intersection of Two Prisms

题目链接

         本题是2010年ICPC亚洲区域赛东京赛区的I题

题意

       求两个无限高棱柱的交。其中一个棱柱是把xy平面上的凸多边形沿z轴无限拉长得到,另外一个棱柱是把xz平面上的凸多边形沿y轴无限拉长得到。输入给出第一个棱柱在xy平面的凸多边形坐标和另外一个棱柱在xz平面的凸多边形坐标,输出相交部分的体积。

分析

        对第一个棱柱,依次枚举其凸多边形的每条边,对应一个平行于z轴的无限大矩形,求出此矩形与第二个棱柱相交得到的多边形。同样地依次枚举第二个棱柱凸多边形的每条边,对应一个平行于y轴的无限大矩形,求出此矩形与第一个棱柱相交得到的多边形。

        这样就求出了相交多面体的每一个面,取相交多面体的第一个面的首个顶点,求此点与各个面的混合积之和,再除以6就是答案。

        需要注意的点:枚举第一个棱柱的侧面(都是平行于z轴的面)和枚举第二个棱柱的侧面(都是平行于y轴的面)时可能产生相同的面,需要去重,平行于z轴的面和平行于y轴的面如果进一步都是垂直于x轴则可能重合。

        再说一个时效可以优化的点:在枚举棱柱侧面求相交多面体的每个面过程中,找出了在xy面或者xz面上的投影多边形(特殊情况垂直于x轴时可快捷计算出yz面上结果矩形),不需要反投影得到真实的三维多边形(即不需要插值计算第三个轴的坐标),因为知道投影多边形与真实多边形的夹角a,投影多边形面积除以cos(a)就是真实多边形的面积。

        具体来说,比如在枚举第一个棱柱的侧面边(x[i],z[i])(x[i+1],z[i+1])时,求dx=x[i+1]-x[i],dz=z[i+1]-z[i],则cos(a)=dx/sqrt(dx*dx+dz*dz)。不过这种方法仍然需要求出真实多边形的一个三维顶点和法向量,用于最终求混合积,整体的计算代价减小约1/3。

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

AC代码

#include <iostream>
#include <iomanip>
using namespace std;#define eps 1e-10
#define N 105
int x1[N], y1[N], x2[N], z2[N]; int m, n, t, e;
struct Point3 {double x, y, z;Point3(double x = 0., double y = 0., double z = 0.): x(x), y(y), z(z) {}
} p[N], s[N<<1], q[N<<1], f[N];
typedef Point3 Vector3;Vector3 operator+ (const Vector3& A, const Vector3& B) {return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
}Vector3 operator- (const Vector3& A, const Vector3& B) {return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
}int dcmp(double x) {return abs(x) < eps ? 0 : (x < 0. ? -1 : 1);
}bool operator== (const Point3& a, const Point3& b) {return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0 && dcmp(a.z - b.z) == 0;
}double Dot(const Vector3& A, const Vector3& B) {return A.x * B.x + A.y * B.y + A.z * B.z;
}Vector3 Cross(const Vector3& A, const Vector3& B) {return Vector3(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);
}Vector3 Area2(const Point3* p, int n) {Vector3 s;for (int i=n-2; i>0; --i) s = s + Cross(p[i]-p[0], p[i+1]-p[0]);return s;
}double interp(int x1, int y1, int x2, int y2, double x) {return ((x-x1)*y2 + (x2-x)*y1) / (x2-x1);
}bool find(const Point3& p) {for (int i=0; i<e; ++i) if (f[i] == p) return true;return false;
}double solve() {for (int i=0; i<m; ++i) cin >> x1[i] >> y1[i];for (int i=0; i<n; ++i) cin >> x2[i] >> z2[i];x1[m] = x1[0]; y1[m] = y1[0]; x2[n] = x2[0]; z2[n] = z2[0];for (int i=t=e=0; i<m; ++i) {int a = min(x1[i], x1[i+1]), b = max(x1[i], x1[i+1]), c = 0;if (a == b) {for (int j=0; j<n; ++j) {int l = min(x2[j], x2[j+1]), r = max(x2[j], x2[j+1]);if (a < l || a > r) continue;if (a == x2[j]) p[c].x = a, p[c].y = y1[i], p[c++].z = z2[j];else if (a != x2[j+1])p[c].x = a, p[c].y = y1[i], p[c++].z = interp(x2[j], z2[j], x2[j+1], z2[j+1], a);}if (c == 2) {p[2].x = p[3].x = a; p[2].y = p[3].y = y1[i+1]; p[2].z = p[1].z; p[3].z = p[0].z; c = 4;f[e].x = a; f[e].y = (y1[i] + y1[i+1]) / 2.; f[e++].z = (p[0].z + p[1].z) / 2.;}} else for (int j=0; j<n; ++j) {int l = min(max(x2[j], a), max(x2[j+1], a)), r = max(min(x2[j], b), min(x2[j+1], b));if (l == r) {if (x2[j] == l) p[c].x = x2[j], p[c].z = z2[j],p[c++].y = interp(x1[i], y1[i], x1[i+1], y1[i+1], x2[j]);} else if (l < r) {if (x2[j] > x2[j+1]) r = l+r, l = r-l, r = r-l;if (x2[j+1] != l) p[c].x = l, p[c].y = interp(x1[i], y1[i], x1[i+1], y1[i+1], l),p[c++].z = interp(x2[j], z2[j], x2[j+1], z2[j+1], l);if (x2[j+1] != r) p[c].x = r, p[c].y = interp(x1[i], y1[i], x1[i+1], y1[i+1], r),p[c++].z = interp(x2[j], z2[j], x2[j+1], z2[j+1], r);}}if (c > 2) s[t] = Area2(p, c), q[t++] = p[0];}for (int i=0; i<n; ++i) {int a = min(x2[i], x2[i+1]), b = max(x2[i], x2[i+1]), c = 0;if (a == b) {for (int j=0; j<m; ++j) {int l = min(x1[j], x1[j+1]), r = max(x1[j], x1[j+1]);if (a < l || a > r) continue;if (a == x1[j]) p[c].x = a, p[c].y = y1[j], p[c++].z = z2[i];else if (a != x1[j+1])p[c].x = a, p[c].y = interp(x1[j], y1[j], x1[j+1], y1[j+1], a), p[c++].z = z2[i];}if (c == 2) {if (find(Point3(a, (p[0].y + p[1].y) / 2., (z2[i] + z2[i+1]) / 2.))) continue;p[2].x = p[3].x = a; p[2].y = p[1].y; p[2].z = p[3].z = z2[i+1]; p[3].y = p[0].y; c = 4;}} else for (int j=0; j<m; ++j) {int l = min(max(x1[j], a), max(x1[j+1], a)), r = max(min(x1[j], b), min(x1[j+1], b));if (l == r) {if (x1[j] == l) p[c].x = x1[j], p[c].y = y1[j],p[c++].z = interp(x2[i], z2[i], x2[i+1], z2[i+1], x1[j]);} else if (l < r) {if (x1[j] > x1[j+1]) r = l+r, l = r-l, r = r-l;if (x1[j+1] != l) p[c].x = l, p[c].y = interp(x1[j], y1[j], x1[j+1], y1[j+1], l),p[c++].z = interp(x2[i], z2[i], x2[i+1], z2[i+1], l);if (x1[j+1] != r) p[c].x = r, p[c].y = interp(x1[j], y1[j], x1[j+1], y1[j+1], r),p[c++].z = interp(x2[i], z2[i], x2[i+1], z2[i+1], r);}}if (c > 2) s[t] = Area2(p, c), q[t++] = p[0];}double ans = 0.;for (int i=1; i<t; ++i) ans += abs(Dot(s[i], q[i]-q[0]));return ans / 6.;
}int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cout << fixed << setprecision(4);while (cin >> m >> n && m) cout << solve() << endl;return 0;
}
        优化版:
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;#define eps 1e-10
#define N 105
double s[N<<1]; int x1[N], _y[N], x2[N], z2[N]; int m, n, t, e;
struct Point {double x, y;Point(double x = 0., double y = 0.): x(x), y(y) {}
} p[N];
struct Point3 {double x, y, z;Point3(double x = 0., double y = 0., double z = 0.): x(x), y(y), z(z) {}void Normalize() {double l = sqrt(x*x + y*y + z*z); x /= l; y /= l; z /= l;}
} q[N<<1], v[N<<1], f[N];
typedef Point3 Vector3;Vector3 operator+ (const Vector3& A, const Vector3& B) {return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
}Vector3 operator- (const Vector3& A, const Vector3& B) {return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
}int dcmp(double x) {return abs(x) < eps ? 0 : (x < 0. ? -1 : 1);
}bool operator== (const Point3& a, const Point3& b) {return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0 && dcmp(a.z - b.z) == 0;
}double Dot(const Vector3& A, const Vector3& B) {return A.x * B.x + A.y * B.y + A.z * B.z;
}Vector3 Cross(const Vector3& A, const Vector3& B) {return Vector3(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);
}double Area2(const Point* p, int n) {double area = p[0].y * (p[n-1].x - p[1].x) + p[n-1].y * (p[n-2].x - p[0].x);for (int i=n-2; i>0; --i) area += p[i].y * (p[i-1].x - p[i+1].x);return area;
}double interp(int x1, int y1, int x2, int y2, double x) {return ((x-x1)*y2 + (x2-x)*y1) / (x2-x1);
}bool find(const Point3& p) {for (int i=0; i<e; ++i) if (f[i] == p) return true;return false;
}double solve() {for (int i=0; i<m; ++i) cin >> x1[i] >> _y[i];for (int i=0; i<n; ++i) cin >> x2[i] >> z2[i];x1[m] = x1[0]; _y[m] = _y[0]; x2[n] = x2[0]; z2[n] = z2[0];for (int i=t=e=0; i<m; ++i) {int a = min(x1[i], x1[i+1]), b = max(x1[i], x1[i+1]), c = 0;if (a != b) {for (int j=0; j<n; ++j) {int l = min(max(x2[j], a), max(x2[j+1], a)), r = max(min(x2[j], b), min(x2[j+1], b));if (l == r) {if (x2[j] == l) p[c].x = x2[j], p[c++].y = z2[j];} else if (l < r) {if (x2[j] > x2[j+1]) r = l+r, l = r-l, r = r-l;if (x2[j+1] != l) p[c].x = l, p[c++].y = interp(x2[j], z2[j], x2[j+1], z2[j+1], l);if (x2[j+1] != r) p[c].x = r, p[c++].y = interp(x2[j], z2[j], x2[j+1], z2[j+1], r);}}if (c > 2) {int dx = x1[i+1] - x1[i], dy = _y[i+1] - _y[i];s[t] = Area2(p, c) * sqrt(dx*dx + dy*dy) / abs(dx);q[t] = Point3(p[0].x, interp(x1[i], _y[i], x1[i+1], _y[i+1], p[0].x), p[0].y);Point3 p1(p[1].x, interp(x1[i], _y[i], x1[i+1], _y[i+1], p[1].x), p[1].y);Point3 p2(p[2].x, interp(x1[i], _y[i], x1[i+1], _y[i+1], p[2].x), p[2].y);v[t] = Cross(p1 - q[t], p2 - p1); v[t++].Normalize();}} else {for (int j=0; j<n; ++j) {int l = min(x2[j], x2[j+1]), r = max(x2[j], x2[j+1]);if (a < l || a > r) continue;if (a == x2[j]) p[c].x = a, p[c++].y = z2[j];else if (a != x2[j+1]) p[c].x = a, p[c++].y = interp(x2[j], z2[j], x2[j+1], z2[j+1], a);}if (c == 2) {f[e].x = a; f[e].y = (_y[i] + _y[i+1]) / 2.; f[e++].z = (p[0].y + p[1].y) / 2.;p[2].x = p[3].x = a; p[2].y = p[1].y; p[3].y = p[0].y; c = 4;v[t].x = 1.; v[t].y = 0.; v[t].z = 0.; q[t].x = a; q[t].y = _y[i]; q[t].z = p[0].y;s[t++] = 2 * abs((p[0].y - p[1].y) * (_y[i] - _y[i+1]));}}}for (int i=0; i<n; ++i) {int a = min(x2[i], x2[i+1]), b = max(x2[i], x2[i+1]), c = 0;if (a != b) {for (int j=0; j<m; ++j) {int l = min(max(x1[j], a), max(x1[j+1], a)), r = max(min(x1[j], b), min(x1[j+1], b));if (l == r) {if (x1[j] == l) p[c].x = x1[j], p[c++].y = _y[j];} else if (l < r) {if (x1[j] > x1[j+1]) r = l+r, l = r-l, r = r-l;if (x1[j+1] != l) p[c].x = l, p[c++].y = interp(x1[j], _y[j], x1[j+1], _y[j+1], l);if (x1[j+1] != r) p[c].x = r, p[c++].y = interp(x1[j], _y[j], x1[j+1], _y[j+1], r);}}if (c > 2) {int dx = x2[i+1] - x2[i], dz = z2[i+1] - z2[i];s[t] = Area2(p, c) * sqrt(dx*dx + dz*dz) / abs(dx);q[t] = Point3(p[0].x, p[0].y, interp(x2[i], z2[i], x2[i+1], z2[i+1], p[0].x));Point3 p1(p[1].x, p[1].y, interp(x2[i], z2[i], x2[i+1], z2[i+1], p[1].x));Point3 p2(p[2].x, p[2].y, interp(x2[i], z2[i], x2[i+1], z2[i+1], p[2].x));v[t] = Cross(p1 - q[t], p2 - p1); v[t++].Normalize();}} else {for (int j=0; j<m; ++j) {int l = min(x1[j], x1[j+1]), r = max(x1[j], x1[j+1]);if (a < l || a > r) continue;if (a == x1[j]) p[c].x = a, p[c++].y = _y[j];else if (a != x1[j+1]) p[c].x = a, p[c++].y = interp(x1[j], _y[j], x1[j+1], _y[j+1], a);}if (c == 2) {f[e].x = a; f[e].y = (p[0].y + p[1].y) / 2.; f[e].z = (z2[i] + z2[i+1]) / 2.;if (find(f[e])) continue;p[2].x = p[3].x = a; p[2].y = p[1].y; p[3].y = p[0].y; c = 4;v[t].x = 1.; v[t].y = 0.; v[t].z = 0.; q[t].x = a; q[t].y = p[0].y; q[t].z = z2[i];s[t++] = 2 * abs((p[0].y - p[1].y) * (z2[i] - z2[i+1])); ++e;}}}double ans = 0.;for (int i=1; i<t; ++i) ans += abs(s[i] * Dot(v[i], q[i]-q[0]));return ans / 6.;
}int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cout << fixed << setprecision(4);while (cin >> m >> n && m) cout << solve() << endl;return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

voxelize_cuda安装教程 python+windows环境

import voxelize_cuda报错 安装步骤&#xff1a; 克隆voxelize项目 官网&#xff1a;https://github.com/YuliangXiu/neural_voxelization_layer.git git clone https://github.com/YuliangXiu/neural_voxelization_layer.git下载一些必备的解析c文件的依赖 官网&#xff1a…

鸿蒙应用开发-录音保存并播放音频

功能介绍&#xff1a; 录音并保存为m4a格式的音频&#xff0c;然后播放该音频&#xff0c;参考文档使用AVRecorder开发音频录制功能(ArkTS)&#xff0c;更详细接口信息请查看接口文档&#xff1a;ohos.multimedia.media (媒体服务)。 知识点&#xff1a; 熟悉使用AVRecorder…

007 日期类型相关工具类

推荐一篇文章 http://t.csdnimg.cn/72F7Jhttp://t.csdnimg.cn/72F7J

agent利用知识来做规划:《KnowAgent: Knowledge-Augmented Planning for LLM-Based Agents》笔记

文章目录 简介KnowAgent思路准备知识Action Knowledge的定义Planning Path Generation with Action KnowledgePlanning Path Refinement via Knowledgeable Self-LearningKnowAgent的实验结果 总结参考资料 简介 《KnowAgent: Knowledge-Augmented Planning for LLM-Based Age…

盛⽔最多的容器【双指针】

首先我们设该容器的两边为左右两边界。 这道题中的&#xff1a;盛⽔最大容量 底 * 高 左右两边界距离 * 左右两边界的较短板。 这道题如果用暴力求解&#xff0c;是个人都能想到怎么做&#xff0c;遍历所有的情况即可。 有没有更好的办法呢&#xff1f;我是搜了资料了解的。我…

Covalent Network(CQT)的以太坊时光机:在 Rollup 时代确保长期数据可用性

以太坊正在经历一场向 “Rollup 时代” 的转型之旅&#xff0c;这一转型由以太坊改进提案 EIP-4844 推动。这标志着区块链技术的一个关键转折&#xff0c;采用了一种被称为“数据块&#xff08;blobs&#xff09;”的新型数据结构。为了与以太坊的扩容努力保持一致&#xff0c;…

MATLAB 自定义生成平面点云(可指定方向,添加噪声)(48)

MATLAB 自定义生成平面点云(可指定方向,添加噪声)(48) 一、算法介绍二、算法步骤三、算法实现1.代码2.效果一、算法介绍 通过这里的平面生成方法,可以生成模拟平面的点云数据,并可以人为设置平面方向,平面大小,并添加噪声来探索不同类型的平面数据。这种方法可以用于…

mysql刨根问底

索引&#xff1a;排好序的数据结构 二叉树&#xff1a; 红黑树 hash表&#xff1a; b-tree&#xff1a; 叶子相同深度&#xff0c;叶节点指针空&#xff0c;索引元素不重复&#xff0c;从左到右递增排序 节点带data btree&#xff1a; 非叶子节点只存储索引&#xff0c;可…

Java_15 删除排序数组中的重复项

删除排序数组中的重复项 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的…

影视作品一键转成动漫,自媒体作者用DomoAI赢麻了

前言 众所周知&#xff0c;在自媒体爆火的那段时间&#xff0c;影视号是最容易起量的&#xff0c;借助高质量的影视&#xff0c;进行剪辑&#xff0c;解说&#xff0c;等二次创作&#xff0c;最终制作成高质量的作品&#xff0c;但是随着自媒体的发展&#xff0c;影视号越来越…

MyBatis是纸老虎吗?(七)

在上篇文章中&#xff0c;我们对照手动编写jdbc的开发流程&#xff0c;对MyBatis进行了梳理。通过这次梳理我们发现了一些之前文章中从未见过的新知识&#xff0c;譬如BoundSql等。本节我想继续MyBatis这个主题&#xff0c;并探索一下MyBatis中的缓存机制。在正式开始梳理前&am…

基于SpringBoot+MyBatis框架的智慧生活商城系统的设计与实现(源码+LW+部署+讲解)

目录 前言 需求分析 可行性分析 技术实现 后端框架&#xff1a;Spring Boot 持久层框架&#xff1a;MyBatis 前端框架&#xff1a;Vue.js 数据库&#xff1a;MySQL 功能介绍 前台功能拓展 商品详情单管理 个人中心 秒杀活动 推荐系统 评论与评分系统 后台功能拓…

测试小白必看:自动化测试入门基础知识

一、首先&#xff0c;什么是自动化测试&#xff1f; 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。通常&#xff0c;在设计了测试用例并通过评审之后&#xff0c;由测试人员根据测试用例中描述的规程一步步执行测试&#xff0c;得到实际结果与期望结果的比较…

Vuex状态、数据持久化(vue2、vue3状态数据持久化)

简介&#xff1a;Vuex是一个仓库&#xff0c;是vue的状态管理工具&#xff0c;存放公共数据&#xff0c;任何组件都可以使用vuex里的公共数据。Vuex提供了插件系统&#xff0c;允许我们使用 vuex-persistedstate插件&#xff0c;将Vuex的状态持久化到本地存储中&#xff0c;解决…

【工具篇】总结比较几种绘画软件的优缺点

目录 一、Visio二、Processon三、draw.io四、亿图图示五、wps 写在文章开头&#xff0c;感谢你的支持与关注&#xff01;小卓的主页 一、Visio Visio 是微软公司开发的一款流程图和图表绘制软件。我们可以用它来创建各种类型的图表&#xff0c;如流程图、组织结构图、网络图、平…

【python从入门到精通】-- 第二战:注释和有关量的解释

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

java的一些内部小知识,类与对象的关系

目录 1. java2. 类与对象的关系 1. java test.java ---- javac --> Test.class ---- java-----> 内存 ----> cpu 源文件 二进制代码 所有正在运行的软件都在内存中有自己的内存空间 jvm —>运行java程序的&#xff0c;java虚拟机 main(); // 内部调用run()run(i…

Fiddler抓包工具之fiddler的常用快捷键

一、常用三个快捷键 ctrlX :清空所有记录 CtrlF&#xff1a;查找 F12&#xff1a;启动或者停止抓包 使用 QuickExec Fiddler2 成了网页调试必备的工具&#xff0c;抓包看数据。Fiddler2自带命令行控制。 fiddler 命令行快捷键&#xff1a;ctrl q &#xff0c;然后 输入 help…

QTday5

头&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> //定时器事件 #include <QTime> //时间类 #include <QtTextToSpeech> //文本转语音类 #include <QMouseEvent> //鼠标事件类 QT_BEGIN_NAMESPACE …

Redis锁,乐观锁与悲观锁

锁 悲观锁 认为什么时候都会出问题&#xff0c;无论做什么都会加锁 乐观锁 很乐观&#xff0c;认为什么时候都不会出问题&#xff0c;所以不会上锁。 更新数据时去判断一下&#xff0c;在此期间&#xff0c;是否有人修改过这个数据 应用于&#xff1a;秒杀场景 **watch*…