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 ...
随机推荐
- 部署WebService服务碰到的一个小问题
在部署WebService服务到IIS上之后,发现一直无法在浏览器访问到编写的asmx文件,一直提示404或403错误.提示当前访问的文件时脚本文件. 1.首先检查了在IIS上部署WebService ...
- 【转载】【MVC 学习 Razor语法】
Razor是MVC3中才有的新的视图引擎.我们知道,在ASP.NET中,ASPX的视图引擎依靠<%和%>来调用C#指令.而MVC3以后有了一套新的使用@标记的Razor语法,使用起来更灵活 ...
- jsoup爬虫,项目实战,欢迎收看
import com.mongodb.BasicDBObject import com.mongodb.DBCollection import org.jsoup.Jsoup import org.j ...
- 通过Maven构建打包Spring boot,并将config配置文件提取到jar文件外
如果通过不同的IDE打包,着实会觉得依赖性太大,并且容易出现错误,操作也比较复杂 同时,spring-boot-maven-plugin的使用感觉,相关配置太少,并且无法满足方便部署和运行的需求. 这 ...
- 问题:java.sql.SQLException: No value specified for parameter 1
解决方案:没有指定参数 String user = req.getParameter("user"); String pwd = req.getParameter("pw ...
- ArcGIS for Server内置JS Viewer的离线部署和配置
很多情况下,在地图服务发布完毕后,我们往往利用 ArcGIS for Server内置的 JS Viewer来查看和检测所发布的地图服务是否满足我们的要求.具体操作如下: 点击开始 -> 所有程 ...
- Linux环境下mysql的root密码忘记解决方法(2种)
方法一: 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以 ...
- MySQL++简单使用记录.md
#1.简介 MySQL++ is a powerful C++ wrapper for MySQL’s C API. Its purpose is to make working with queri ...
- Python+selenium之键盘事件
keuys()类提供键盘上所有的按键方法.send_keys()方法可以用来模拟键盘输入. from selenium import webdriver from selenium.webdriver ...
- HTML 标签(一)
HTML HTML:超文本编辑语言(标签语言) 浏览器顺序渲染,从上到下,从左到右 是树型的 html格式 标签的属性是关键 meta标签 可提供有关页面的元信息 <meta charset=& ...