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 ...
随机推荐
- 2017年3月14日-----------乱码新手自学.net 之Authorize特性与Forms身份验证(登陆验证、授权小实例)
有段时间没写博客了,最近工作比较忙,能敲代码的时间也不多. 我一直有一个想法,想给单位免费做点小软件,一切思路都想好了,但是卡在一个非常基础的问题上:登陆与授权. 为此,我看了很多关于微软提供的Ide ...
- c# Redis操作类
需要添加StackExchange.Redis.dll引用 using System; using System.Collections.Generic; using System.IO; using ...
- I/O流操做总结(三)
说实话,其实我并不是很喜欢Java这门语言,尽管它很强大,有很多现成的API可以调用 但我总感觉它把简单的事情弄得太过复杂,甚至有时候会让人迷失 弄不清到底是为了写出东西,还是为了语言本身 我学习的第 ...
- python的subprocess模块(写的不错留作查询)
python的subprocess模块 subprocess模块是python从2.4版本开始引入的模块.主要用来取代 一些旧的模块方法,如os.system.os.spawn*.os.popen*. ...
- AutoIt上传非input控件方式的文件脚本
AutoIt目前最新是v3版本,这是一个使用类似BASIC脚本语言的免费软件,它设计用于Windows GUI(图形用户界面)中进行自动化操作.它利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现自动 ...
- Java和ABAP中的几种引用类型的分析和比较
Java编程语言中几种不同的引用类型是面试时经常容易被问到的问题:强引用,软引用,弱引用,虚引用. 其实除了Java之外,某些 其他编程语言也有类似概念,比如ABAP.今天我们就来比较一下. 根据AB ...
- 三维GIS-室内寻径功能实现
期末,要交一个大作业,正巧之前跑国图借书的时候,晕头转向的,国图内居然没有导航!!!借这个机会做一个室内导航的demo,只是半成品,还需要加入室内定位,匹配一下坐标才能在实际中使用. demo:利用蜂 ...
- Winform C# 编程 1
http://b6ec263c.wiz03.com/share/s/2SX2oY0nX4f32CY5ax1bapaL01Wmfc0B-QfB2pS1y13peTbq
- 多线程程序设计-Thread的一些方法
run():是程序中会和会和其他线程“同时”执行的部分. wait():使得当前线程进入等待状态,等待的线程不会主动进入到线程队列中排队等待cpu资源,必须由其他线程调用notify()方法通知它 ...
- prometheus-简介及安装
监控是整个产品周期中最重要的一环,及时预警减少故障影响免扩大,而且能根据历史数据追溯问题. 对系统不间断实时监控 实时反馈系统当前状态 保证业务持续性运行 监控系统 监控方案 告警 特点 适用 Zab ...