HLG 1506 屠夫和狙击手【判断点在线段上+线段与圆相交】
Description |
DOTA是一个大学生中非常受欢迎的一款游戏,游戏中天灾军团和近卫军团一直处于对抗状态,如果近卫军团的世界之树或者天灾军团的冰封王座被摧毁,那么游戏会立即结束。游戏中最有意思的是就两个军团的基地内都有一个可以补充各自英雄能量的泉水。当然泉水不仅仅是一个能量补给站,而且还会很快杀死想靠近的敌方英雄。但是无论如何泉水奈何不了近卫军团的矮人狙击手,因为矮人狙击手的攻击范围要比泉水远很多。因此矮人狙击手甚至有能力拆掉一个泉水。有一个生命值不多的矮人狙击手要攻击天灾军团的泉水,这个猥琐的行为是天灾军团不能容忍的,天灾军团的英雄屠夫是在看不下去了,屠夫准备出马收拾这个狙击手。屠夫有一把钩子,可以将一条线上单位钩到自己面前(只要这个单位在屠夫和屠夫钩子瞄准的坐标点之间的线段上,包括瞄准点在内屠夫都可以办到)。尽管屠夫没有把握杀死矮人狙击手,但是如果矮人狙击手进入泉水的攻击范围泉水会立即杀死狙击手的。
|
Input |
本题有多组测试数据,第一行输入三个整数,泉水的坐标 x1 y1 和泉水的攻击半径r,第二行输入四个整数,分别代表屠夫的位置(x2 y2)和屠夫钩子的目标位置(x3 y3)。第三行输入两个整数,代表狙击手的位置 x4 y4。 |
Output |
如果矮人狙击手必死,输出 DEAD 并换行 否则输出 LIVE 并换行 |
Sample Output |
4 4 4 2 2 -5 0 6 6 |
Hint |
DEAD |
思路:如果点在圆内,或者点在线段上并且线段与圆有交点,则输出DEAD,否则...
代码如下:
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> using namespace std; int mindis(int p1xx, int p1yy, int p2xx, int p2yy, int qxx, int qyy, int rr) { int flag=1; double sxx, syy, k, dis; if(p1xx==p2xx) {sxx=p1xx;syy=qyy;flag=0;} if(p1yy==p2yy) {sxx=qxx;syy=p1yy;flag=0;} if(flag) { k=1.0*(p2yy-p1yy)/(p2xx-p1xx); sxx=(k*k*p1xx+k*(qyy-p1yy)+qxx)/(k*k+1); syy=k*(sxx-p1xx)+p1yy; } if(min(p1xx,p2xx)<=sxx&&sxx<=max(p1xx,p2xx)) dis=sqrt((qxx-sxx)*(qxx-sxx)+(qyy-syy)*(qyy-syy)); else dis=min(sqrt((qxx-p1xx)*(qxx-p1xx)+(qyy-p1yy)*(qyy-p1yy)),sqrt((qxx-p2xx)*(qxx-p2xx)+(qyy-p2yy)*(qyy-p2yy))); //printf("%.2lf\n", dis); if(dis-rr>0) return 0; return 1; } int main() { int ox, oy, r, p1x, p1y, p2x, p2y, ax, ay; while(scanf("%d%d%d%d%d%d%d%d%d", &ox, &oy, &r, &p1x, &p1y, &p2x, &p2y, &ax, &ay)!=EOF) { int flag=0; int dis=(ox-ax)*(ox-ax)+(oy-ay)*(oy-ay); if(dis<=r*r) flag=1; if(((p1x-ax)*(p2y-ay)-(p2x-ax)*(p1y-ay)==0)&&((p1x-ax)*(p2x-ax)<=0)&&(p1y-ay)*(p2y-ay)<=0 &&mindis(p1x, p1y, p2x, p2y, ox, oy, r)) flag=1; if(flag==1) printf("DEAD\n"); else printf("LIVE\n"); } }