UVA 5984 - Save the Students!

 

题目地址 : http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=519&page=show_problem&problem=3995

 

简单的计算几何(整数几何)。

 

题目中数据出的并不大,所以直接枚举所有点,判断是否在范围内即可(以及判重)。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define sign(a) ((a)>0?1:(((a)<0?-1:0)))
using namespace std;

int n,m;
int flg[152][152];
int cx[52],cy[52],cr[52];
int sx[52],sy[52],sl[52];


struct Point{
	int x,y;
	Point(){}
	Point(int a,int b){x=a,y=b;}
}t[52][3];

int xmult(Point p,Point l1,Point l2){
	return (p.x-l2.x)*(l1.y-l2.y)-(l1.x-l2.x)*(p.y-l2.y);
}

int di(Point p,Point l1,Point l2){ // 判断点是否在线段上
	return !xmult(p,l1,l2) && (l1.x-p.x)*(l2.x-p.x)<=0 && (l1.y-p.y)*(l2.y-p.y)<=0;
}

int sd(Point p1,Point p2,Point l1,Point l2){ // 判断p1、p2是否在线段同侧
	return sign(xmult(l1,p1,l2))*xmult(l1,p2,l2)>0;
}

int deal(int i,Point p){
	if(di(p,t[i][0],t[i][1]) || di(p,t[i][0],t[i][2]) || di(p,t[i][1],t[i][2])) return 1;
	if(sd(p,t[i][0],t[i][1],t[i][2]) && sd(p,t[i][1],t[i][0],t[i][2]) && sd(p,t[i][2],t[i][1],t[i][0]))
		return 1;
	return 0;
}

int main(){
	int T,n,i,j,cnt1,cnt2,cnt3,x,y,sum,l1,l2,r1,r2;
	char ch[3];
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		cnt1=cnt2=cnt3=0;
		while(n--){
			scanf("%s",ch);
			if(ch[0]=='C'){
				scanf("%d%d%d",&cx[cnt1],&cy[cnt1],&cr[cnt1]);
				cnt1++;
			}
			else if(ch[0]=='S'){
				scanf("%d%d%d",&sx[cnt2],&sy[cnt2],&sl[cnt2]);
				cnt2++;
			}
			else{
				for(i=0;i<3;i++)
					scanf("%d%d",&t[cnt3][i].x,&t[cnt3][i].y);
				cnt3++;
			}
		}
		sum=0;
		memset(flg,0,sizeof(flg));
		for(i=0;i<cnt1;i++){
			l1=cx[i]-cr[i];
			r1=cx[i]+cr[i];
			l2=cy[i]-cr[i];
			r2=cy[i]+cr[i];
			for(x=l1;x<=r1;x++)
				 for(y=l2;y<=r2;y++)
				 	if(flg[x+50][y+50]) continue;
				 	else if((cx[i]-x)*(cx[i]-x)+(cy[i]-y)*(cy[i]-y)<=cr[i]*cr[i]){
			 			flg[x+50][y+50]++;
			 			sum++;
					}
		} 
		for(i=0;i<cnt2;i++){
			l1=sx[i];
			r1=sx[i]+sl[i];
			l2=sy[i];
			r2=sy[i]+sl[i];
			for(x=l1;x<=r1;x++)
				 for(y=l2;y<=r2;y++)
				 	if(flg[x+50][y+50]) continue;
				 	else{
			 			flg[x+50][y+50]++;
			 			sum++;
					}
		}
		for(i=0;i<cnt3;i++){
			l1=min(t[i][0].x,min(t[i][1].x,t[i][2].x));
			r1=max(t[i][0].x,max(t[i][1].x,t[i][2].x));
			l2=min(t[i][0].y,min(t[i][1].y,t[i][2].y));
			r2=max(t[i][0].y,max(t[i][1].y,t[i][2].y));
			for(x=l1;x<=r1;x++)
				 for(y=l2;y<=r2;y++)
				 	if(flg[x+50][y+50]) continue;
				 	else if(deal(i,Point(x,y))){
			 			flg[x+50][y+50]++;
			 			sum++;
					}
		}
		printf("%d\n",sum);
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值