[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」激光发生器的更多相关文章

  1. LOJ#2039. 「SHOI2015」激光发生器(计算几何)

    题面 传送门 题解 如果我初中科学老师知道我有一天计算的时候入射角不等于反射角不知道会不会把我抓起来打一顿-- 这题本质上就是个模拟,需要的芝士也就计蒜几盒的那点,不过注意细节很多,放到考场上只能看看 ...

  2. 【LOJ】#2039. 「SHOI2015」激光发生器

    题解 我永远都写不对计算几何-- 首先找到反射的线段比较好找,扫一遍所有线段然后找交点在镜子上并且交点离起点最近的那条线段 然后旋转的时候,有可能是顺时针,也有可能是逆时针,要找出法线,然后判断法线和 ...

  3. loj#2038. 「SHOI2015」超能粒子炮・改

    题目链接 loj#2038. 「SHOI2015」超能粒子炮・改 题解 卢卡斯定理 之后对于%p分类 剩下的是个子问题递归 n,k小于p的S可以预处理,C可以卢卡斯算 代码 #include<c ...

  4. loj #2037. 「SHOI2015」脑洞治疗仪

    #2037. 「SHOI2015」脑洞治疗仪   题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...

  5. Loj #2036. 「SHOI2015」自动刷题机

    link : https://loj.ac/problem/2036 这个显然具有单调性,N小的话更容易A题,不仅因为A一次题减少的代码,并且A题的下限也低. 所以直接上二分就行了,注意上限一定不要设 ...

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. LeetCode-5:Longest Palindromic Substring(最长回文子字符串)

    描述:给一个字符串s,查找它的最长的回文子串.s的长度不超过1000. Input: "babad" Output: "bab" Note: "aba ...

  2. python raw string

    path = r'C:\a\b\c.txt' r'字符串' 是raw 字符串的意思, 其中的字符串不会转义,即不解释 \ . 作用之一:可以用来保存Windows的路径,直接从资源管理器复制来粘贴,不 ...

  3. fscanf和fgets用法

    首先要对fscanf和fgets这两个文件函数的概念有深入的了解,对于字符串输入而言这两个函数有一个典型的区别是: fscanf读到空格或者回车时会把空格或回车转化为/(字符串结束符)而fgets函数 ...

  4. HihoCoder1641 : 热门号码([Offer收割]编程练习赛37)(模拟)

    描述 1 2 3 ABC DEF 4 5 6 GHI JKL MNO 7 8 9 PQRS TUV WXYZ * 0 # 我们知道电话拨号盘上数字会有若干字母对应,例如2对应ABC,7对应PQRS. ...

  5. HihoCoder1653 : 公平分队([Offer收割]编程练习赛39)(贪心)

    描述 小Hi和小Ho在玩一个战争游戏.游戏中2N个战斗单位,其中第i个单位的战斗力是Ai. 现在小Hi和小Ho要各选N个单位组成队伍,当然他们都希望自己队伍的总战斗力越大越好. 为了使分队更加公平,经 ...

  6. bzoj 2251: 外星联络 后缀Trie

    题目大意 http://www.lydsy.com/JudgeOnline/problem.php?id=2251 题解 本来以为这道题应该从01序列的性质入手 结果就想歪了 等自己跳出了01序列这个 ...

  7. poj1325机器工作——二分图最小点覆盖

    题目:http://poj.org/problem?id=1325 二分图求最大匹配,即为最小点覆盖: 一开始我写得较麻烦,求出最大匹配又去搜增广路,打标记求最小点覆盖: 然而两种方法都没写“ans= ...

  8. Oracle字符串截断

    字段.SUBSTR(string,start_position,[length]) 求子字符串,返回字符串解释:string 元字符串, start_position 开始位置(从0开始), leng ...

  9. SSO跨域 CodeProject

    http://www.codeproject.com/Articles/114484/Single-Sign-On-SSO-for-cross-domain-ASP-NET-appl 翻译: http ...

  10. petrozavodsk1

    A 转化模型和相当于求解小于n/2的最大的和n互质的数字, 显然可以证明所求和n/2相距 O(logn) ,从 n/2 开始向下枚举然后判定即可. B 上下界网络流? C 从底层开始向上走贪心选下层节 ...