您的位置:首页 > 其它

Bzoj1829 [Usaco2010 Mar]starc星际争霸

2017-04-12 23:16 218 查看
Time Limit: 1 Sec  Memory Limit: 64 MB
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个数值的): 

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

Sample Output

J
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

Gold

 

数学问题 计算几何 半平面交

似乎很卡精度的样子

设出$x$,$y$,$z$三个未知量分别表示三种单位的战斗力,各种不等式都可以表示成$ax+by+cz≥0$ 的形式。

注意到z是正数,那么可以将表达式除以z,得到一个直线表达式

对全部的直线做半平面交,可以围出一个凸包(或凸壳?)来。

询问一条直线的时候,将凸包每个顶点带入求值,若值均为正或均为负,则可以判定结果,否则战局不明

 

精度卡飞,干脆学(chao)了Claris神犇的写法

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1e-12;
const double eps2=1e-2;
const int mxn=405;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct point{
double x,y;
point operator + (point b){return (point){x+b.x,y+b.y};}
point operator - (point b){return (point){x-b.x,y-b.y};}
point operator * (double v){return (point){x*v,y*v};}
point operator / (double v){return (point){x/v,y/v};}
}p[mxn];
double dot(point a,point b){
return a.x*b.x+a.y*b.y;
}
double Cross(point a,point b){
return a.x*b.y-a.y*b.x;
}
typedef point Vector;
double dist(Vector a){
return sqrt(a.x*a.x+a.y*a.y);
}
struct line{
point x; Vector v;
double a;
void ang(){a=atan2(v.y,v.x);return;}
bool operator < (line b)const{
return a<b.a;
}
}L[mxn],q[mxn];
int cnt=0;
inline void newline(point a,point b){
L[++cnt].x=a;L[cnt].v=b-a;return;
}
point segins(line &a,line &b){//交点
point x=a.x-b.x;
double t=Cross(b.v,x)/Cross(a.v,b.v);
return a.x+a.v*t;
}
bool Left(point a,line b){
return Cross(b.v,a-b.x)>0;
}
int hd,tl;
void solve(){
newline((point){0,0},(point){100,1});
newline((point){1,100},(point){0,0});
newline((point){0,eps2},(point){100,eps2});
newline((point){100,0},(point){100,100});
newline((point){100,100},(point){0,100});
newline((point){eps2,100},(point){eps2,0});//边界

for(int i=1;i<=cnt;i++) L[i].ang();
sort(L+1,L+cnt+1);
hd=tl=1;q[tl]=L[1];
for(int i=2;i<=cnt;i++){
while(hd<tl && !Left(p[tl-1],L[i]))tl--;
while(hd<tl && !Left(p[hd],L[i]))hd++;
if(fabs(Cross(q[tl].v,L[i].v))<eps){
if(!Left(q[tl].x,L[i]))q[tl]=L[i];
}
else q[++tl]=L[i];
if(hd<tl)p[tl-1]=segins(q[tl-1],q[tl]);
}
while(hd<tl && !Left(p[tl-1],q[hd]))tl--;
p[tl]=segins(q[tl],q[hd]);
return;
}
void query(){
int a,b,c,d,e,f;
a=read();b=read();c=read();d=read();e=read();f=read();
a-=d;b-=e;c-=f;
int flag=0;
for(int i=hd;i<=tl;i++){
double tmp=p[i].x*a+p[i].y*b+c;
if(tmp>-eps)flag|=1;
if(tmp<eps)flag|=2;
}
if(flag==1)printf("J\n");
else if(flag==2)printf("B\n");
else printf("U\n");
return;
}
int n,m;
int main(){
freopen("starc.in","r",stdin);
freopen("starc.out","w",stdout);
int i,j;char win[3];
n=read();m=read();
int a,b,c,d,e,f;
for(i=1;i<=n;i++){
scanf("%s",win);
a=read();b=read();c=read();d=read();e=read();f=read();
if(win[0]=='B')swap(a,d),swap(b,e),swap(c,f);
a-=d;b-=e;c-=f;
if(!a && !b)continue;
if(b){
point A=(point){0,-c/(double)b};
point B=(point){100,(-100.0*a-c)/(double)b};
point C=A;C.y+=1;
if(C.x*a+C.y*b+c>0)newline(A,B);
else newline(B,A);
}
else{
point A=(point){-c/(double)a,0};
point B=(point){-c/(double)a,100};
point C=A;C.x-=1;
if(C.x*a+C.y*b+c>0)newline(A,B);
else newline(B,A);
}
}
solve();
while(m--)query();
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: