[LOJ 2039] 「SHOI2015」激光发生器
[LOJ 2039] 「SHOI2015」激光发生器
链接
题解
分为两个部分
第一个是求直线之间的交点找到第一个触碰到的镜面
第二个是求直线经过镜面反射之后的出射光线
第一个很好做,第二个就是将入射光线旋转,注意旋转后在哪一面(可能到镜面背后去)
代码
// Copyright lzt
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long, long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i, j, k) for (register int i = (int)(j); i <= (int)(k); i++)
#define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
x = 10 * x + ch - '0';
ch = getchar();
}
return x * f;
}
const int maxn = 110;
const double eps = 1e-8;
const double pi = acos(-1);
struct Point {
double x, y;
Point(double _x = 0, double _y = 0) {
x = _x; y = _y;
}
Point operator + (const Point &b) const {
return (Point){x + b.x, y + b.y};
}
Point operator - (const Point &b) const {
return (Point){x - b.x, y - b.y};
}
Point operator * (const double &b) const {
return (Point){x * b, y * b};
}
};
typedef Point Vector;
struct Line {
Point x; Vector y;
Line() {}
Line(Point _x, Vector _y) {
x = _x; y = _y;
}
};
struct LLL {
Point p1, p2;
double a, b;
} A[maxn];
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 Len(const Vector &a) {
return sqrt(Dot(a, a));
}
int dcmp(double x) {
return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
}
Point intersect(const Line &a, const Line &b) {
Vector v = a.x - b.x;
double t = Cross(b.y, v) / Cross(a.y, b.y);
return a.x + a.y * t;
}
double Angle(const Vector &a, const Vector &b) {
return acos(Dot(a, b) / Len(a) / Len(b));
}
bool onseg(const Point &p, const Point &a, const Point &b) {
return dcmp(Dot(a - p, b - p)) <= 0 && dcmp(Cross(a - p, a - p)) == 0;
}
Vector rotate(const Vector &a, double b) {
return (Vector){a.x * cos(b) - a.y * sin(b), a.y * cos(b) + a.x * sin(b)};
}
double X, Y, dx, dy;
int n;
void work() {
X = read(), Y = read(), dx = read(), dy = read();
n = read();
rep(i, 1, n) {
A[i].p1.x = read(); A[i].p1.y = read();
A[i].p2.x = read(); A[i].p2.y = read();
A[i].a = read(), A[i].b = read();
}
Point nw = (Point){X, Y};
Vector v = (Vector){dx, dy};
rep(_, 1, 10) {
int ind = 0; double nwdis = 1e9;
rep(i, 1, n) {
if (dcmp(Cross(A[i].p1 - A[i].p2, v)) == 0) continue;
Point p = intersect(Line(A[i].p1, A[i].p2 - A[i].p1), Line(nw, v));
if (onseg(p, A[i].p1, A[i].p2) && dcmp(Dot(v, p - nw)) > 0) {
double dis = Len(p - nw);
if (dis < nwdis) nwdis = dis, ind = i;
}
}
if (!ind) {
if (_ == 1) puts("NONE");
break;
}
printf("%d ", ind);
nw = intersect(Line(A[ind].p1, A[ind].p2 - A[ind].p1), Line(nw, v));
if (dcmp(Dot(A[ind].p1 - A[ind].p2, v)) == 0) v = v * (-1);
else {
Vector nwv;
if (dcmp(Dot(A[ind].p1 - A[ind].p2, v)) > 0) nwv = A[ind].p1 - A[ind].p2;
else nwv = A[ind].p2 - A[ind].p1;
double alpha = pi / 2 - Angle(nwv, v);
if (dcmp(Cross(nwv, v)) > 0) v = rotate(nwv, alpha * A[ind].a / A[ind].b - pi / 2);
else v = rotate(nwv, pi / 2 - alpha * A[ind].a / A[ind].b);
}
}
}
int main() {
#ifdef LZT
freopen("in", "r", stdin);
#endif
work();
#ifdef LZT
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
}
[LOJ 2039] 「SHOI2015」激光发生器的更多相关文章
- LOJ#2039. 「SHOI2015」激光发生器(计算几何)
题面 传送门 题解 如果我初中科学老师知道我有一天计算的时候入射角不等于反射角不知道会不会把我抓起来打一顿-- 这题本质上就是个模拟,需要的芝士也就计蒜几盒的那点,不过注意细节很多,放到考场上只能看看 ...
- 【LOJ】#2039. 「SHOI2015」激光发生器
题解 我永远都写不对计算几何-- 首先找到反射的线段比较好找,扫一遍所有线段然后找交点在镜子上并且交点离起点最近的那条线段 然后旋转的时候,有可能是顺时针,也有可能是逆时针,要找出法线,然后判断法线和 ...
- loj#2038. 「SHOI2015」超能粒子炮・改
题目链接 loj#2038. 「SHOI2015」超能粒子炮・改 题解 卢卡斯定理 之后对于%p分类 剩下的是个子问题递归 n,k小于p的S可以预处理,C可以卢卡斯算 代码 #include<c ...
- loj #2037. 「SHOI2015」脑洞治疗仪
#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...
- Loj #2036. 「SHOI2015」自动刷题机
link : https://loj.ac/problem/2036 这个显然具有单调性,N小的话更容易A题,不仅因为A一次题减少的代码,并且A题的下限也低. 所以直接上二分就行了,注意上限一定不要设 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
随机推荐
- 获取url的参数
function getPrams () { var url, urlPrams, urlPramsArr=[], item=[], prams={}; url = location.href; if ...
- 基于jQuery Ajax实现无刷新文件上传
最近因项目需求更改,需要实现选择文件后即时上传至服务器,然后提交后,加载xls表格内容到jqgrid表格中,文件上传功能实现示例: 前端jsp页面: <form id="uploadF ...
- AtCoder Grand Contest #026 A - Colorful Slimes 2
Time Limit: 2 sec / Memory Limit: 1024 MB Score : 200200 points Problem Statement Takahashi lives in ...
- 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)
前言: shiro因为其简单.可靠.实现方便而成为现在最常用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登录注销功能使用之外,也会根据惯例在文章最后总结一 ...
- AtCoder Grand Contest 014 D:Black and White Tree
题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_d 题目翻译 给你一棵树,每次任选一个点染色,先手染白色,后手染黑色.如果最后存在一个白色的点 ...
- Python 静态方法和类方法的区别
python staticmethod and classmethod Though classmethod and staticmethod are quite similar, there’s a ...
- WaitHandle.WaitAll 方法在WPF工程中的应用
因为WaiAll需要多线程支持, 而WPF是STA模式, 可以通过以下方式实现WaitAll ManualResetEvent[] events: foreach (ManualResetEvent ...
- cocos2dx 3.0 用ClippingNode做游戏的新手引导
转自:http://blog.csdn.net/star530/article/details/20851263 本篇介绍的是用ClippingNode 做游戏的新手引导,额,或者说是做新手引导的一种 ...
- Java中的内部类介绍(1)
栗子1: package campu; //外部类 class Out{ private int age =12; //内部类 class In{ public void print(){ Syste ...
- 原生及jq方式使用ajax
1.原生js实现Ajax方法: // 封装ajax()方法 function ajax(url,fnSucc,fnFaild){ //1.创建Ajax 对象 if(window.XMLHttpRequ ...