[USACO Mar10]星牛争霸StarCowraft解题报告

题目


分析

首先可以发现,我们能够把三种单位的战斗力同时乘以一个数而不改变结果。因此,不妨设第三种单位的战斗力S3=1.出于方便,不妨记x=S1,y=S2

对于一场比赛,我们能够写出一个类似这样的式子:

j1x+j2y+j3<=b1x+b2y+b3(当然也有可能是>=)

整理后得到一个类似这样的式子:

ax+by<=c

后面的朋友们,大声告诉我这叫什么?

没错,半平面!

所以做法就很简单了:对所有测试局的半平面求交,其交集(或曰‘核’)是一个凸多边形。将其所有顶点求出。在试图判断一次新的战斗时,显然该场战斗对应于一条直线,如果凸多边形的所有顶点均在直线一侧,那么该战斗的结果是确定的,否则不定。

注意,那个“单位之差不超过100”倍的条件也是要写出来的。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<deque>
#include<vector>
using namespace std;
const double eps=1e-10,pi=acos(-1.0),INF=1e10;
const int SIZE=2010;
class Point{
public:
	double x,y;
};
void print(const Point &p){
	cout<<"("<<p.x<<" "<<p.y<<")";
}
double cross(const Point &a,const Point &b){
	return a.x*b.y-b.x*a.y;
}
class H_Plane{//那啥啥的game,不对plane
public:
	double a,b,c;//ax+by<=c
	double pa;//极角
	void print(void)const{
		cout<<"极角:"<<pa<<" 不等式:"<<a<<"x+"<<b<<"y<="<<c;
		cout<<" 方程:y="<<-a/b<<"x+"<<c/b<<endl;
	}
	void assign(char winner,double j1,double j2,double j3,double b1,double b2,double b3){
		a=j1-b1,b=j2-b2,c=b3-j3;//这是按Bessie赢算的
		if(winner=='J') a*=-1,b*=-1,c*=-1;
		pa=atan2(-a,b);
		if(pa<0) pa+=2*pi;
	}
};
void print(const H_Plane &h){
	h.print();
}
bool cmp(const H_Plane &a,const H_Plane &b){
	return a.pa<b.pa;
}
bool inside(const Point &p,const H_Plane &h){
	return h.a*p.x+h.b*p.y<h.c-eps;
}
Point inter(const H_Plane &s,const H_Plane &t){//要求s,t极角不同
	Point ans;
	ans.x=(s.b*t.c-s.c*t.b)/(s.b*t.a-s.a*t.b);
	ans.y=(s.a*t.c-s.c*t.a)/(s.a*t.b-s.b*t.a);
	return ans;
}
void HPL_intersection(H_Plane h[],int n,deque<H_Plane> &Q){
	//要求此时已经计算出所有半平面的极角,存于h[1..n]
	//Q中返回约束了核的那些半平面
	sort(h+1,h+1+n,cmp);
	int tot=0;
	for(int i=1;i<=n;i++){//多个约束取最紧者
		if(tot==0||fabs(h[tot].pa-h[i].pa)>eps) h[++tot]=h[i];
		else if(h[i].c<h[tot].c) h[tot]=h[i];
	}
	n=tot;
	Q.clear();
	for(int i=1;i<=n;i++){
		while(Q.size()>=2&&!inside(inter(Q.back(),Q[Q.size()-2]),h[i])) Q.pop_back();
		while(Q.size()>=2&&!inside(inter(Q[0],Q[1]),h[i])) Q.pop_front();
		Q.push_back(h[i]);
	}
	while(Q.size()>=2&&!inside(inter(Q.back(),Q[Q.size()-2]),Q[0])) Q.pop_back();
}
int check(const vector<Point> &v,const H_Plane &h){
	double mx=-INF,mn=INF;
	for(int i=0;i<v.size();i++){
		double now=h.a*v[i].x+h.b*v[i].y;
		mx=max(mx,now);
		mn=min(mn,now);
	}
	if(mx<h.c-eps) return 1;//符合h的判断
	else if(mn>h.c+eps) return -1;//不符合h的判断
	else return 0;
}
int N,M;
H_Plane test_battle[SIZE];
deque<H_Plane> core;
vector<Point> core_points;
void work(void){
	HPL_intersection(test_battle,N,core);
	for(int i=0;i<core.size()-1;i++){
		core_points.push_back(inter(core[i],core[i+1]));
	}
	core_points.push_back(inter(core[0],core.back()));
	int j1,j2,j3,b1,b2,b3;
	H_Plane h;
	for(int i=1;i<=M;i++){
		scanf("%d%d%d%d%d%d\n",&j1,&j2,&j3,&b1,&b2,&b3);
		h.assign('B',j1,j2,j3,b1,b2,b3);
		int flag=check(core_points,h);
		if(flag==1) printf("B\n");
		else if(flag==-1) printf("J\n");
		else printf("U\n");
	}
}
void read(void){
	scanf("%d%d\n",&N,&M);
	char c;
	int j1,j2,j3,b1,b2,b3;
	for(int i=1;i<=N;i++){
		scanf("%c%d%d%d%d%d%d\n",&c,&j1,&j2,&j3,&b1,&b2,&b3);
		test_battle[i].assign(c,j1,j2,j3,b1,b2,b3);
	}
	test_battle[++N].assign('B',1,0,0,0,0,100);
	test_battle[++N].assign('J',100,0,0,0,0,1);
	test_battle[++N].assign('B',0,1,0,0,0,100);
	test_battle[++N].assign('J',0,100,0,0,0,1);
	test_battle[++N].assign('B',1,0,0,0,100,0);
	test_battle[++N].assign('J',100,0,0,0,1,0);
}
int main(){
	freopen("starc.in","r",stdin);
	freopen("starc.out","w",stdout);
	read();
	work();
	return 0;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值