Hoj 11195
题目链接: http://acm.hnu.cn:8080/online/?action=problem&type=show&id=11195
#include
<
iostream
>
#include < string .h >
#include < math.h >
#define eps 1e-3
using namespace std;
struct point
{
double x, y;
point(){}
void read(){
scanf( " %lf,%lf " , & x, & y);
}
void write(){
printf( " %.0lf,%.0lf\n " , x, y);
}
};
struct line
{
char flag;
point a, b;
line(){}
void read(){
getchar();
scanf( " %c %lf,%lf %lf,%lf " , & flag, & a.x, & a.y, & b.x, & b.y);
}
void write(){
printf( " %c %.0lf,%.0lf %.0lf,%.0lf\n " , flag, a.x, a.y, b.x, b.y);
}
};
// 精度控制
int sig( double a)
{ return (a > eps) - (a < - eps);}
// 判两直线平行
int parallel(point u1,point u2,point v1,point v2){
return sig((u1.x - u2.x) * (v1.y - v2.y) - (v1.x - v2.x) * (u1.y - u2.y));
}
// 计算cross product (P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
// (op-sp)·(op-ep)点积
double dotmul(point sp, point ep, point op){
return (op.x - sp.x) * (op.x - ep.x) + (op.y - sp.y) * (op.y - ep.y);
}
// 判两点在线段异侧,点在线段上返回0
int opposite_side(point p1,point p2,point l1,point l2){
return xmult(l1,p1,l2) * xmult(l1,p2,l2) <- eps;
}
// 判两线段相交,不包括端点和部分重合
int intersect_ex(point u1,point u2,point v1,point v2){
// if(!parallel(u1,u2,v1,v2))
return opposite_side(u1,u2,v1,v2) && opposite_side(v1,v2,u1,u2);
// else return 0;
}
// 计算两直线交点,注意事先判断直线是否平行!
point intersection(point u1,point u2,point v1,point v2){
point ret = u1;
double t = ((u1.x - v1.x) * (v1.y - v2.y) - (u1.y - v1.y) * (v1.x - v2.x))
/ ((u1.x - u2.x) * (v1.y - v2.y) - (u1.y - u2.y) * (v1.x - v2.x));
ret.x += (u2.x - u1.x) * t;
ret.y += (u2.y - u1.y) * t;
return ret;
}
// 一个double的平方
double sqr( double a)
{ return a * a;}
// 返回p向量的模的平方
double mo(point p)
{ return p.x * p.x + p.y * p.y;}
// 两点距离
double dist(point a, point b)
{ return sqrt( sqr(a.x - b.x) + sqr(a.y - b.y) );}
// 返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置
point rotate(point o, double alpha, point p)
{
point tp;
p.x -= o.x; p.y -= o.y;
tp.x = p.x * cos(alpha) - p.y * sin(alpha) + o.x;
tp.y = p.y * cos(alpha) + p.x * sin(alpha) + o.y;
return tp;
}
// 返回顶角在o点,起始边为os,终止边为oe的夹角(单位:弧度)
double angle(point o, point s, point e)
{
point os, oe;
os.x = s.x - o.x; os.y = s.y - o.y;
oe.x = e.x - o.x; oe.y = e.y - o.y;
double cosfi, norm, fi;
cosfi = dotmul(s, e, o);
norm = sqrt(mo(os) * mo(oe));
cosfi /= norm;
if (sig(cosfi - 1.0 ) >= 0 ) return 0 ;
if (sig(cosfi + 1.0 ) <= 0 ) return M_PI;
fi = acos(cosfi);
// o.write(); s.write(); e.write();
return fi;
}
// 返回op向量与线段s反射的向量(p在s上)
point reflct(point o, point p, line s)
{
point new_dic;
double ang = angle(p, o, s.a);
if ( sig(ang - M_PI / 2 ) > 0 ) ang = M_PI - ang;
ang = M_PI - 2 * ang;
new_dic = rotate(p, ang, o);
if (angle(p, o, s.a) != angle(p, new_dic, s.b) ) new_dic = rotate(p, 2 * M_PI - ang, o);
new_dic.x -= p.x;
new_dic.y -= p.y;
return new_dic;
}
line l[ 101 ];
int n, answer[ 101 ];
struct nod
{
point ini, dic;
}q[ 101 ];
void work(point a, point b)
{
int cnt = 0 , close = - 1 , open = 0 ;
point exp, new_ini, ini = a, dic = b, cro, new_dic;
double mindis;
int minnum;
memset(answer, 0 , sizeof (answer));
q[ 0 ].ini = ini;
q[ 0 ].dic = dic;
while (close < open)
{
close ++ ;
ini = q[close].ini;
dic = q[close].dic;
exp.x = ini.x + 5000 * dic.x;
exp.y = ini.y + 5000 * dic.y;
// 把射线变成线段
int i;
mindis = 999999999.0 ; minnum = - 1 ;
for (i = 0 ; i < n; i ++ )
{
if ( intersect_ex(ini, exp, l[i].a, l[i].b) ) // 两线段相交
{
new_ini = intersection(ini, exp, l[i].a, l[i].b);
if ( mindis > dist( ini, new_ini) )
{
minnum = i;
mindis = dist(ini, new_ini);
}
}
}
new_ini = intersection(ini, exp, l[minnum].a, l[minnum].b);
if (minnum == - 1 ) continue ;
if (l[minnum].flag == ' D ' )
{
answer[minnum] = 1 ;
continue ;
}
if (l[minnum].flag == ' S ' )
{
open ++ ;
q[open].ini = new_ini;
q[open].dic = dic;
}
open ++ ;
new_dic = reflct(ini, new_ini, l[minnum]);
q[open].ini = new_ini;
q[open].dic = new_dic;
}
}
void out ()
{
int flag = 0 ;
for ( int i = 0 ; i < n; i ++ ) if (answer[i])
{
flag = 1 ;
printf( " %d\n " ,i + 1 );
}
if ( ! flag) puts( " NO BEAMS DETECTED " );
}
int main()
{
int test, x = 0 ;
point ini, dic;
scanf( " %d " , & test);
while (test -- )
{
printf( " DATA SET #%d\n " , ++ x);
ini.read(); dic.read();
scanf( " %d " , & n);
for ( int i = 0 ; i < n; i ++ )
{
l[i].read();
}
work(ini, dic);
out ();
}
}
#include < string .h >
#include < math.h >
#define eps 1e-3
using namespace std;
struct point
{
double x, y;
point(){}
void read(){
scanf( " %lf,%lf " , & x, & y);
}
void write(){
printf( " %.0lf,%.0lf\n " , x, y);
}
};
struct line
{
char flag;
point a, b;
line(){}
void read(){
getchar();
scanf( " %c %lf,%lf %lf,%lf " , & flag, & a.x, & a.y, & b.x, & b.y);
}
void write(){
printf( " %c %.0lf,%.0lf %.0lf,%.0lf\n " , flag, a.x, a.y, b.x, b.y);
}
};
// 精度控制
int sig( double a)
{ return (a > eps) - (a < - eps);}
// 判两直线平行
int parallel(point u1,point u2,point v1,point v2){
return sig((u1.x - u2.x) * (v1.y - v2.y) - (v1.x - v2.x) * (u1.y - u2.y));
}
// 计算cross product (P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
// (op-sp)·(op-ep)点积
double dotmul(point sp, point ep, point op){
return (op.x - sp.x) * (op.x - ep.x) + (op.y - sp.y) * (op.y - ep.y);
}
// 判两点在线段异侧,点在线段上返回0
int opposite_side(point p1,point p2,point l1,point l2){
return xmult(l1,p1,l2) * xmult(l1,p2,l2) <- eps;
}
// 判两线段相交,不包括端点和部分重合
int intersect_ex(point u1,point u2,point v1,point v2){
// if(!parallel(u1,u2,v1,v2))
return opposite_side(u1,u2,v1,v2) && opposite_side(v1,v2,u1,u2);
// else return 0;
}
// 计算两直线交点,注意事先判断直线是否平行!
point intersection(point u1,point u2,point v1,point v2){
point ret = u1;
double t = ((u1.x - v1.x) * (v1.y - v2.y) - (u1.y - v1.y) * (v1.x - v2.x))
/ ((u1.x - u2.x) * (v1.y - v2.y) - (u1.y - u2.y) * (v1.x - v2.x));
ret.x += (u2.x - u1.x) * t;
ret.y += (u2.y - u1.y) * t;
return ret;
}
// 一个double的平方
double sqr( double a)
{ return a * a;}
// 返回p向量的模的平方
double mo(point p)
{ return p.x * p.x + p.y * p.y;}
// 两点距离
double dist(point a, point b)
{ return sqrt( sqr(a.x - b.x) + sqr(a.y - b.y) );}
// 返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置
point rotate(point o, double alpha, point p)
{
point tp;
p.x -= o.x; p.y -= o.y;
tp.x = p.x * cos(alpha) - p.y * sin(alpha) + o.x;
tp.y = p.y * cos(alpha) + p.x * sin(alpha) + o.y;
return tp;
}
// 返回顶角在o点,起始边为os,终止边为oe的夹角(单位:弧度)
double angle(point o, point s, point e)
{
point os, oe;
os.x = s.x - o.x; os.y = s.y - o.y;
oe.x = e.x - o.x; oe.y = e.y - o.y;
double cosfi, norm, fi;
cosfi = dotmul(s, e, o);
norm = sqrt(mo(os) * mo(oe));
cosfi /= norm;
if (sig(cosfi - 1.0 ) >= 0 ) return 0 ;
if (sig(cosfi + 1.0 ) <= 0 ) return M_PI;
fi = acos(cosfi);
// o.write(); s.write(); e.write();
return fi;
}
// 返回op向量与线段s反射的向量(p在s上)
point reflct(point o, point p, line s)
{
point new_dic;
double ang = angle(p, o, s.a);
if ( sig(ang - M_PI / 2 ) > 0 ) ang = M_PI - ang;
ang = M_PI - 2 * ang;
new_dic = rotate(p, ang, o);
if (angle(p, o, s.a) != angle(p, new_dic, s.b) ) new_dic = rotate(p, 2 * M_PI - ang, o);
new_dic.x -= p.x;
new_dic.y -= p.y;
return new_dic;
}
line l[ 101 ];
int n, answer[ 101 ];
struct nod
{
point ini, dic;
}q[ 101 ];
void work(point a, point b)
{
int cnt = 0 , close = - 1 , open = 0 ;
point exp, new_ini, ini = a, dic = b, cro, new_dic;
double mindis;
int minnum;
memset(answer, 0 , sizeof (answer));
q[ 0 ].ini = ini;
q[ 0 ].dic = dic;
while (close < open)
{
close ++ ;
ini = q[close].ini;
dic = q[close].dic;
exp.x = ini.x + 5000 * dic.x;
exp.y = ini.y + 5000 * dic.y;
// 把射线变成线段
int i;
mindis = 999999999.0 ; minnum = - 1 ;
for (i = 0 ; i < n; i ++ )
{
if ( intersect_ex(ini, exp, l[i].a, l[i].b) ) // 两线段相交
{
new_ini = intersection(ini, exp, l[i].a, l[i].b);
if ( mindis > dist( ini, new_ini) )
{
minnum = i;
mindis = dist(ini, new_ini);
}
}
}
new_ini = intersection(ini, exp, l[minnum].a, l[minnum].b);
if (minnum == - 1 ) continue ;
if (l[minnum].flag == ' D ' )
{
answer[minnum] = 1 ;
continue ;
}
if (l[minnum].flag == ' S ' )
{
open ++ ;
q[open].ini = new_ini;
q[open].dic = dic;
}
open ++ ;
new_dic = reflct(ini, new_ini, l[minnum]);
q[open].ini = new_ini;
q[open].dic = new_dic;
}
}
void out ()
{
int flag = 0 ;
for ( int i = 0 ; i < n; i ++ ) if (answer[i])
{
flag = 1 ;
printf( " %d\n " ,i + 1 );
}
if ( ! flag) puts( " NO BEAMS DETECTED " );
}
int main()
{
int test, x = 0 ;
point ini, dic;
scanf( " %d " , & test);
while (test -- )
{
printf( " DATA SET #%d\n " , ++ x);
ini.read(); dic.read();
scanf( " %d " , & n);
for ( int i = 0 ; i < n; i ++ )
{
l[i].read();
}
work(ini, dic);
out ();
}
}