Bzoj1829 [Usaco2010 Mar]starc星际争霸
Submit: 152 Solved: 82
Description
《星际争霸2》全面公测啦!Farmer John和Bessie正在测试中——在1v1的战役中使用一些不同的策略来对抗对方的部队。星际争霸2的游戏目标就是在战役中打败你对手的军队。每个选手的军队都在战役中拼杀。一支军队由若干3种不同类型的单位所组成,不同单位有着不同的由正实数表示的,且不被选手所知道的力量值:cattlebruisers 的力量是S1,cow templars 的力量是S2,ultracows的力量是S3。唯一提供的信息是,没有一个单位的力量值超过另一个单位力量值的100倍。一支军队的总力量值,是其中各自单独的单位的力量值的总和。比如一支军队除了其他单位有23个cattlebruisers,那么这支军队单独从cattlebruisers就能获得23*S1的力量值。当两支对立的军队在战役中厮杀,有着更高力量值的军队将获得胜利。如果两支军队的力量值恰好相同,那么将随机产生一个获胜方。Farmer John 和 Bessie 进行了 N (0 <= N <= 300) 局的“测试战役”。在第 i 局测试战役中,Farmer John 有 J1_i 个 cattlebruisers,J2_i 个 cow templars 以及 J3_i 个 ultracows(0 <= J1_i + J2_i + J3_i <= 1,000)。相似的,Bessie的军队有 B1_i 个 cattlebruisers,B2_i 个 cow templars 以及 B3_i 个 ultracows (0 <= B1_i + B2_i + B3_i <= 1,000)。当他们的军队战斗结束后,FJ 和 Bessie 将胜者以一个单独的“胜利字母” V_i 记录下来:"J"表示 Farmer John 赢得了战役;"B" 表示 Bessie 获胜了。虽然这些结果是他们唯一所拥有的信息,但是他们希望预测一些额外的战役的结果——如果告知他们两支对立军队的组成。尽管,可能对于一些比赛他们是无法确定到底哪一方一定能获胜的。给出已经结束的 N 场测试战役的结果,写一个程序来确定(如果可能的话)M (1 <=M <=2,000)场额外战役的获胜方。 所有给出的测试战役的结果都是正确的。至少存在一种合法的力量值的取值符合这些结果。为了示范一下力量值函数的计算,考虑如下战役,并且有 S1=9.0, S2=7.0, S3=4.0 (当然,Farmer John 和 Bessie 都是不知道这3个数值的): ![](http://www.lydsy.com/JudgeOnline/images/1829.jpg)
![](http://www.lydsy.com/JudgeOnline/images/1829.jpg)
Input
* Line 1: 两个用空格隔开的整数;N和 M * Lines 2..N+1: 第 i+1 行用7个用空格分开的数据来描述第i场测试战役:V_i, J1_i, J2_i, J3_i,B1_i, B2_i, 和 B3_i——第一个是胜利字母,接下来是6个整数 * Lines N+2..N+M+1: 第i+N+1行描述了第i场额外战役,这里给出6个用空格分开的整数 J1_i, J2_i, J3_i, B1_i, B2_i, 和 B3_i
Output
* Lines 1..M: 第i包含第i场额外战役的结果:"J"表示Farmer John一定能赢,"B"表示Bessie一 定能赢,"U"表示不确定——也就是不可能利用给出的信息推断出谁一定能获胜。
Sample Input
3 3
J 6 5 4 5 4 7
B 5 4 2 3 5 5
J 9 0 10 8 2 7
6 6 4 5 4 7
9 0 10 8 2 6
3 4 8 4 4 6
J 6 5 4 5 4 7
B 5 4 2 3 5 5
J 9 0 10 8 2 7
6 6 4 5 4 7
9 0 10 8 2 6
3 4 8 4 4 6
Sample Output
J
J
U
J
U
HINT
一开始的两场战役已经在题目中给出过解释了。最后一场战役是不能利用已有信息推断出结果的。
具体来说,对于 S_1=9.0, S_2=7.0, S_3=4.0 和 S_1=12.0, S_2=20.0, S_3=10.0
这两组不同的数值都符合输入信息,但是却能使的最后一场测试战役产生不同的结果。
Source
数学问题 计算几何 半平面交
似乎很卡精度的样子
设出$x$,$y$,$z$三个未知量分别表示三种单位的战斗力,各种不等式都可以表示成$ax+by+cz≥0$ 的形式。
注意到z是正数,那么可以将表达式除以z,得到一个直线表达式
对全部的直线做半平面交,可以围出一个凸包(或凸壳?)来。
询问一条直线的时候,将凸包每个顶点带入求值,若值均为正或均为负,则可以判定结果,否则战局不明
精度卡飞,干脆学(chao)了Claris神犇的写法
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 const double eps=1e-12; 8 const double eps2=1e-2; 9 const int mxn=405; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct point{ 17 double x,y; 18 point operator + (point b){return (point){x+b.x,y+b.y};} 19 point operator - (point b){return (point){x-b.x,y-b.y};} 20 point operator * (double v){return (point){x*v,y*v};} 21 point operator / (double v){return (point){x/v,y/v};} 22 }p[mxn]; 23 double dot(point a,point b){ 24 return a.x*b.x+a.y*b.y; 25 } 26 double Cross(point a,point b){ 27 return a.x*b.y-a.y*b.x; 28 } 29 typedef point Vector; 30 double dist(Vector a){ 31 return sqrt(a.x*a.x+a.y*a.y); 32 } 33 struct line{ 34 point x; Vector v; 35 double a; 36 void ang(){a=atan2(v.y,v.x);return;} 37 bool operator < (line b)const{ 38 return a<b.a; 39 } 40 }L[mxn],q[mxn]; 41 int cnt=0; 42 inline void newline(point a,point b){ 43 L[++cnt].x=a;L[cnt].v=b-a;return; 44 } 45 point segins(line &a,line &b){//交点 46 point x=a.x-b.x; 47 double t=Cross(b.v,x)/Cross(a.v,b.v); 48 return a.x+a.v*t; 49 } 50 bool Left(point a,line b){ 51 return Cross(b.v,a-b.x)>0; 52 } 53 int hd,tl; 54 void solve(){ 55 newline((point){0,0},(point){100,1}); 56 newline((point){1,100},(point){0,0}); 57 newline((point){0,eps2},(point){100,eps2}); 58 newline((point){100,0},(point){100,100}); 59 newline((point){100,100},(point){0,100}); 60 newline((point){eps2,100},(point){eps2,0});//边界 61 62 for(int i=1;i<=cnt;i++) L[i].ang(); 63 sort(L+1,L+cnt+1); 64 hd=tl=1;q[tl]=L[1]; 65 for(int i=2;i<=cnt;i++){ 66 while(hd<tl && !Left(p[tl-1],L[i]))tl--; 67 while(hd<tl && !Left(p[hd],L[i]))hd++; 68 if(fabs(Cross(q[tl].v,L[i].v))<eps){ 69 if(!Left(q[tl].x,L[i]))q[tl]=L[i]; 70 } 71 else q[++tl]=L[i]; 72 if(hd<tl)p[tl-1]=segins(q[tl-1],q[tl]); 73 } 74 while(hd<tl && !Left(p[tl-1],q[hd]))tl--; 75 p[tl]=segins(q[tl],q[hd]); 76 return; 77 } 78 void query(){ 79 int a,b,c,d,e,f; 80 a=read();b=read();c=read();d=read();e=read();f=read(); 81 a-=d;b-=e;c-=f; 82 int flag=0; 83 for(int i=hd;i<=tl;i++){ 84 double tmp=p[i].x*a+p[i].y*b+c; 85 if(tmp>-eps)flag|=1; 86 if(tmp<eps)flag|=2; 87 } 88 if(flag==1)printf("J\n"); 89 else if(flag==2)printf("B\n"); 90 else printf("U\n"); 91 return; 92 } 93 int n,m; 94 int main(){ 95 freopen("starc.in","r",stdin); 96 freopen("starc.out","w",stdout); 97 int i,j;char win[3]; 98 n=read();m=read(); 99 int a,b,c,d,e,f; 100 for(i=1;i<=n;i++){ 101 scanf("%s",win); 102 a=read();b=read();c=read();d=read();e=read();f=read(); 103 if(win[0]=='B')swap(a,d),swap(b,e),swap(c,f); 104 a-=d;b-=e;c-=f; 105 if(!a && !b)continue; 106 if(b){ 107 point A=(point){0,-c/(double)b}; 108 point B=(point){100,(-100.0*a-c)/(double)b}; 109 point C=A;C.y+=1; 110 if(C.x*a+C.y*b+c>0)newline(A,B); 111 else newline(B,A); 112 } 113 else{ 114 point A=(point){-c/(double)a,0}; 115 point B=(point){-c/(double)a,100}; 116 point C=A;C.x-=1; 117 if(C.x*a+C.y*b+c>0)newline(A,B); 118 else newline(B,A); 119 } 120 } 121 solve(); 122 while(m--)query(); 123 return 0; 124 }
本文为博主原创文章,转载请注明出处。