LA 5007 Detector Placement 模拟
题意:
给出一束光线(射线),和一块三角形的棱镜 以及 棱镜的折射率,问光线能否射到X轴上,射到X轴上的坐标是多少。
分析:
其实直接模拟就好了,注意到题目中说不会发生全反射,所以如果射到棱镜中的话就一定能射出来。
一开始判断一下能否经过棱镜折射,不能的话直接算和X轴有没有交点或者交点的坐标。
- 然后就是根据入射光线T1求入射点P1,注意直线可能和三角形的两条边都有交点,但最近的那个才是入射点。
找到入射点就求法线,算角度,利用折射公式算折射角,求出折射光线T2。 - 第二部分其实和上面的过程是一样的,求出射点,根据公式算出射角,最后求得出射光线。
- 出射光线和X轴求交点,或者没有交点。
上个样例的光路图,仅供参考:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
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;
void read() { scanf("%lf%lf", &x, &y); }
void print() { printf(" (%.2f, %.2f) \n", x, y); }
Point(double x = 0, double y = 0): x(x), y(y) {}
};
typedef Point Vector;
Point operator + (const Point& A, const Point& B) {
return Point(A.x + B.x, A.y + B.y);
}
Point operator - (const Point& A, const Point& B) {
return Point(A.x - B.x, A.y - B.y);
}
Point operator * (const Point& A, double p) {
return Point(A.x * p, A.y * p);
}
Point operator / (const Point& A, double p) {
return Point(A.x / p, A.y / p);
}
double Dot(const Vector& A, const Vector& B) {
return A.x * B.x + A.y * B.y;
}
double Cross(const Vector& A, const Vector& B) {
return A.x * B.y - A.y * B.x;
}
double Length(Vector A) { return sqrt(Dot(A, A)); }
double Distance(Point A, Point B) { return Length(A - B); }
Vector Normal(Vector v) { return Vector(-v.y, v.x); }
Vector Rotate(Vector A, double rad) {
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
struct Line
{
Point P;
Vector v;
Line() {}
Line(Point P, Vector v) : P(P), v(v) {}
};
bool OnSegment(Point P, Point a1, Point a2) {
Vector v1 = a1 - P, v2 = a2 - P;
return dcmp(Cross(v1, v2)) == 0 && dcmp(Dot(v1, v2)) < 0;
}
bool isParallel(const Line& A, const Line& B) {
return dcmp(Cross(A.v, B.v)) == 0;
}
Point GetLineIntersection(Line L1, Line L2, double& t)
{
Vector u = L1.P - L2.P;
t = Cross(L2.v, u) / Cross(L1.v, L2.v);
return L1.P + L1.v * t;
}
double u;
Point p[3], s, t;
Line L[3];
int main()
{
Point hehe(0, 0), haha(10, 0);
Line flat(hehe, haha);
int T; scanf("%d", &T);
while(T--) {
s.read(); t.read();
for(int i = 0; i < 3; i++) p[i].read();
scanf("%lf", &u);
L[0] = Line(p[0], p[1] - p[0]);
L[1] = Line(p[1], p[2] - p[1]);
L[2] = Line(p[2], p[0] - p[2]);
Line T(s, t - s); //入射光线
int in_id = -1;
Point in_P; //入射点
for(int i = 0; i < 3; i++) {
double t;
if(isParallel(T, L[i])) continue; //直线平行,没有交点
Point p = GetLineIntersection(T, L[i], t);
if(dcmp(t) <= 0) continue;
if(!OnSegment(p, L[i].P, L[i].P + L[i].v)) continue; //交点不在线段上
if(in_id == -1 || Distance(s, p) < Distance(s, in_P)) {
in_P = p; in_id = i;
}
}
if(in_id == -1) { //没有射到棱镜上
double t;
if(dcmp(T.v.y) >= 0) printf("Error\n");
else printf("%.3f\n", GetLineIntersection(T, flat, t).x);
continue;
}
//printf("in_Point:");
//in_P.print();
Vector normal = Normal(L[in_id].v); //计算第一次折射的法线
if(dcmp(Dot(normal, T.v)) < 0) normal.x = -normal.x, normal.y = -normal.y; //调整法线的方向
double theta = asin(fabs(Cross(T.v, normal)) / Length(T.v) / Length(normal) / u);//计算折射角
Line T2; T2.P = in_P; //折射光线
if(dcmp(Cross(normal, T.v)) > 0) T2.v = Rotate(normal, theta);
else T2.v = Rotate(normal, -theta);
int out_id;
Point out_P; //出射点
for(int i = 0; i < 3; i++) if(i != in_id) {
if(isParallel(T2, L[i])) continue;
double t;
Point p = GetLineIntersection(T2, L[i], t);
if(dcmp(t) <= 0) continue;
if(!OnSegment(p, L[i].P, L[i].P + L[i].v)) continue;
out_P = p;
out_id = i;
}
//printf("out_Point:");
//out_P.print();
Vector normal2 = Normal(L[out_id].v);
if(dcmp(Dot(T2.v, normal2)) < 0) normal2.x = -normal2.x, normal2.y = -normal2.y;
double theta2 = asin(fabs(Cross(T2.v, normal2)) / Length(T2.v) / Length(normal2) * u);
Line T3; T3.P = out_P;
if(dcmp(Cross(normal2, T2.v)) > 0) T3.v = Rotate(normal2, theta2);
else T3.v = Rotate(normal2, -theta2);
double t;
if(dcmp(T3.v.y) >= 0) printf("Error\n");
else printf("%.3f\n", GetLineIntersection(T3, flat, t).x);
}
return 0;
}
LA 5007 Detector Placement 模拟的更多相关文章
- hdu3712 Detector Placement
题意:给一束激光,一个三棱柱,三棱柱会折射光,问这束激光最终是否会和y = 0相交: 分析:模拟题,为了方便处理折射角,事先求出每条边的向内和向外的法向量: findpoint : 找第一交点 ste ...
- La Vie en rose (模拟)
#include<bits/stdc++.h> using namespace std; ; ; int T, n, m; char str1[maxm], str2[maxn]; int ...
- LA 3486 Cells(判祖先+栈模拟dfs)
https://vjudge.net/problem/UVALive-3486 题意: 判断u是否是v的祖先. 思路: 很简单,dfs遍历,记录每个节点第一次访问时的时间戳 in[i] 和第二次访问时 ...
- LA 4119 Always an integer (数论+模拟)
ACM-ICPC Live Archive 一道模拟题,题意是问一个给出的多项式代入正整数得到的值是否总是整数. 这题是一道数论题,其实对于这个式子,我们只要计算1~最高次项是否都满足即可. 做的时候 ...
- [ACM_模拟][ACM_数学] LA 2995 Image Is Everything [由6个视图计算立方体最大体积]
Description Your new company is building a robot that can hold small lightweight objects. The robo ...
- HDU 5745 La Vie en rose (DP||模拟) 2016杭电多校联合第二场
题目:传送门. 这是一道阅读理解题,正解是DP,实际上模拟就能做.pij+1 指的是 (pij)+1不是 pi(j+1),判断能否交换输出即可. #include <iostream> # ...
- LA 2995 立方体成像(模拟)
题目链接:https://vjudge.net/problem/UVALive-2995 这道题的主要难点在于三维坐标系的建立,然后在坐标系中进行迭代更新. 注意用宏定义来简化代码. AC代码: #i ...
- LA 3708 墓地雕塑(模拟)
题目链接:https://vjudge.net/problem/UVALive-3708 这道题的思路也是比较难想. 首先根据上一题(Uva 11300)可知,要想让移动距离最短,那么至少要使一个雕塑 ...
- Codeforces 738D. Sea Battle 模拟
D. Sea Battle time limit per test: 1 second memory limit per test :256 megabytes input: standard inp ...
随机推荐
- oracle备份imp命令大全
oracle中imp命令详细解释 Oracle的导入有用程序(Import utility)同意从数据库提取数据,而且将数据写入操作系统文件.imp使用的基本格式:imp[username[/pass ...
- Web可用性设计的247条指导方针
首页可用性设计 首页元素要清晰的关注用户的关键任务(避免“增加功能倾向(featuritis)”) 如果网站比较大,那么首页应包含搜索输入框 首页要十分清楚的提供产品(内容)分类 在首页或首页内一次点 ...
- 使用CRA开发的基于React的UI组件发布到内网NPM上去
前言:构建的ES组件使用CNPM发布内网上过程 1. 使用Create-React-APP开的组件 如果直接上传到NPM,你引用的时候会报: You may need an appropriate l ...
- 在Unity3d中解析Lua脚本的方法
由于近期项目中提出了热更新的需求,因此本周末在Lua的陪伴下度过.对Lua与Unity3d的搭配使用,仅仅达到了一个初窥门径的程度,记录一二于此.水平有限,欢迎批评指正. 网络上关于Lua脚本和Uni ...
- Mysql order by 排序 varchar 类型数据
Mysql order by 排序 varchar 类型数据 varchar 类型字段排序, 会將数字当成字符串来处理. 排序规则一般是从左到右一位位来比较. +0之后 就转化成INT 类型排序 ...
- git上传布置代码 git优势
ftp 软件 可直接上传至服务器但不便于管理 Git上传 GitHub/码云/codinghub 登录服务器 ssh 协议登录 ssh 账户@ip地址 密码 mkdir 创建文件 workspace ...
- str中的join方法,fromkeys(),set集合,深浅拷贝(重点)
一丶对之前的知识点进行补充 1.str中的join方法.把列表转换成字符串 # 将列表转换成字符串,每个元素之间用_拼接 s = "_".join(["天",& ...
- AngularJS中最重要的核心功能
以下是AngularJS中最重要的核心功能: 数据绑定: 模型和视图组件之间的数据自动同步. 适用范围: 这些对象参考模型.它们充当控制器和视图之间的胶水. 控制器: 这些Javascript函数绑定 ...
- Google Chrome 浏览器的备用(离线)安装程序
Google Chrome 浏览器的备用(离线)安装程序(适用于 Windows) 如果您在使用 http://www.google.com/chrome 上的标准安装程序下载 Chrome 浏览器时 ...
- ubuntu下安装ffmpeg扩展
可通过PPA进行安装 sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next sudo apt-get update sudo apt-get ...