sgu 110 Dungeon

这道题是计算几何,这是写的第一道计算几何,主要是难在如何求入射光线的反射光线。

我们可以用入射光线 - 入射光线在法线(交点到圆心的向量)上的投影*2 来计算反射光线,自己画一个图,非常清晰明了。

具体到程序里,我们可以 v2 = v1 - fa / Length(fa) * 2 * ( Dot(v1, fa) /
Length(fa)) 来求,简单来说就是用内积(点积)求出入射光线在法线上的长度,然后用法线的单位向量乘这个长度就可以了。


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#define N 55
#define inf 0x7f7f7f7f
using namespace std;

struct Point3
{
double x, y, z;
Point3(double x=0, double y=0, double z=0):x(x), y(y), z(z) { }
};
typedef Point3 Vector3;
const double eps = 1e-9;

int dcmp(double x)
{
if (fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}

int n;
double r[N];
Point3 Begin, circle[N];
Vector3 Direct;

Vector3 operator + (Vector3 A, Vector3 B) { return Vector3(A.x+B.x, A.y+B.y, A.z+B.z); }
Vector3 operator - (Point3 A, Point3 B) { return Vector3(A.x-B.x, A.y-B.y, A.z-B.z); }
Vector3 operator * (Vector3 A, double p) { return Vector3(A.x*p, A.y*p, A.z*p); }
Vector3 operator / (Vector3 A, double p) { return Vector3(A.x/p, A.y/p, A.z/p); }

double min(double x, double y) { return x < y ? x : y; }

double Dot (Vector3 A, Vector3 B) { return A.x*B.x + A.y*B.y + A.z*B.z; }
double Length (Vector3 A) { return sqrt(Dot(A, A)); }
double Angle (Vector3 A, Vector3 B) { return acos(Dot(A, B) / Length(A) / Length(B)); }
Vector3 Cross (Vector3 A, Vector3 B) { return Vector3(A.y*B.z - A.z*B.y, A.z*B.x - A.x*B.z, A.y*B.z - A.z*B.y); }
double disPointLine(Point3 P, Point3 A, Point3 B)
{
Vector3 v1, v2;
v1 = B - A; v2 = P - A;
return Length(Cross(v1, v2)) / Length(v1);
}

int main()
{
scanf("%d", &n);
double x, y, z;
for (int i = 1; i <= n; ++i)
{
scanf("%lf%lf%lf%lf", &x, &y, &z, &r[i]);
circle[i] = Point3(x, y, z);
}
scanf("%lf%lf%lf", &x, &y, &z); Begin = Point3(x, y ,z);
scanf("%lf%lf%lf", &x, &y, &z); Direct = Point3(x, y, z) - Begin;
int nowcircle = 0;
for (int w = 1; w <= 11; ++w)
{
int nextcircle = 0;
double mindis = inf;
for (int i = 1; i <= n; ++i)
{
if (i == nowcircle) continue;
double a, b, c;
Point3 nc = circle[i];
a = Direct.x*Direct.x + Direct.y*Direct.y + Direct.z*Direct.z;
b = 2 * ((Begin.x-nc.x) * Direct.x + (Begin.y-nc.y)*Direct.y + (Begin.z-nc.z)*Direct.z);
c = (Begin.x-nc.x)*(Begin.x-nc.x) + (Begin.y-nc.y)*(Begin.y-nc.y) + (Begin.z-nc.z)*(Begin.z-nc.z) - r[i]*r[i];
double delta;
delta = b*b - 4*a*c;
if (delta < 0) continue;
double ans1, ans2;
ans1 = (-b + sqrt(delta)) / (2*a);
ans2 = (-b - sqrt(delta)) / (2*a);
if (dcmp(ans1) < 0 && dcmp(ans2) < 0) continue;
else if (dcmp(ans1) < 0 && ans2 < mindis)
{
mindis = ans2;
nextcircle = i;
}
else if (dcmp(ans2) < 0 && ans1 < mindis)
{
mindis = ans1;
nextcircle = i;
}
else if (min(ans1, ans2) < mindis)
{
mindis = min(ans1, ans2);
nextcircle = i;
}
}
if (!nextcircle) break;
else if (w == 11)
{
printf(" etc.");
break;
}
else
{
if (w == 1) printf("%d", nextcircle);
else printf(" %d", nextcircle);
Point3 jiao;
Vector3 v1, v2, fa;
jiao = Begin + Direct*mindis; v1 = Direct;
fa = circle[nextcircle] - jiao;
v2 = (fa / Length(fa)) * (2 * Dot(v1, fa) / Length(fa));
nowcircle = nextcircle;
Begin = jiao; Direct = v1 - v2;
}
}
printf("\n");
}

sgu 110 Dungeon

时间: 2024-10-05 09:14:34

sgu 110 Dungeon的相关文章

【转】[专题学习][计算几何]

原文地址:http://www.cnblogs.com/ch3656468/archive/2011/03/02/1969303.html 基本的叉积.点积和凸包等东西就不多说什么了,网上一搜一大堆,切一些题目基本熟悉了就差不多了. 一些基本的题目可以自己搜索,比如这个blog:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 接下来,研究了半平面交,思想方法看07年朱泽园的国家队论文,模板代码参考自我校大牛韬哥: http://www.o

SGU 275 To xor or not to xor (高斯消元)

题目地址:SGU 275 首先,贪心的思想,每一二进制位上要尽量是1,而能不能是1用高斯消元来解决.当该位有一个可以使之为1的变元时,就说明这位可以为1,而且令该变元控制该位,然后向低位消元. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h>

poj2251:Dungeon Master

最初没有注意到结果是要求最小的步数,那么就成了最基本的迷宫找到一条出路的问题并记下找到出路时,所花的步数,那么很容易得到代码如下: 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 6 #define MAX 1000000 7 int l,r,c,coun; 8 char m[30][30][30]; 9 bool flag[30][30]

SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流

The Glorious Karlutka River =) Time Limit:500MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 438 Appoint description: Description A group of Mtourists are walking along the Karlutka river. They want to cross

sgu Kalevich Strikes Back

这道题就是求一个大矩形被n个矩形划分成n+1个部分的面积,这些矩形之间不会相交,可能包含.. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #define maxn 120100 6 using namespace std; 7 8 long long s[maxn]; 9 vector<int>g[maxn]; 10 i

sgu To xor or not to xor

题意:从n个数中,选择一些数,使得异或最大. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define ll __int64 5 using namespace std; 6 7 ll c[110][110]; 8 int n; 9 ll cc; 10 11 void gauss() 12 { 13 int i,j; 14 ll ans=0; 15 for(int r=0; r&l

数学计数原理(P&#243;lya,高精度):SGU 294 He&#39;s Circles

He's Circles He wrote n letters "X" and "E" in a circle. He thought that there were 2n possibilities to do it, because each letter may be either "X" or "E". But Qc noticed that some different sequences of letters ca

sgu Ice-cream Tycoon

题意:供应商提供n块价格为c的冰淇淋,一个学生想买n块冰淇淋,手中的钱数总共有t元,为了不让买n块冰淇淋所花费的钱数不超过t元,先尽可能卖给这个学生便宜的冰淇淋. 如果这个学生不能买到所需要的冰淇淋则输出“UNHAPPY”,能则输出“HAPPY”. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 200000 5 using namespace std; 6 7

sgu 463 - Walking around Berhattan

K - Walking around Berhattan Time Limit:250MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 463 Description As you probably know, Berhattan is a district of Berland's largest city and it consists of equal squar