ssoj2868(最大不相交区间)

5 篇文章 0 订阅

【题意】在二维平面上以(0,0)为左下角,(w,d)为右上角的矩形区域内有一些点,每个点代表一个人,每个人将会面对一个方向(东南西北),一个人的视野范围是以该点为顶点的直角,角平分线与其所面对的方向平行,角的两条边会与矩形交于两点,矩形上两点之间的部分,为该人的可视部分。为了让每个人都能知道时间,你需要在矩形的边界上放置一些时钟(视为一个点),使得每个人的可以部分内都至少有一个时钟,求最少需要放置几个时钟。

【思路】记录下每个点在边界上的交点,记录区间,然后沿逆时针方向将边界拉成直线(由于是环要*2),寻找最大不相交的区间个数(没有公共点)

【代码】

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define maxn 2003
#define inf 100000007
using namespace std;
pair<int,int > p[maxn];
int n,w,d,len,s[maxn],t[maxn];
int get(){
    char c;while(!isdigit(c=getchar()));
    int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
    return v;
}
void init(){
    n=get();w=get();d=get();
    len=(w+d)<<1;
    int x,y;char ch;int x1,y1,x2,y2;
    for(int i=1;i<=n;++i){
	    x=get();y=get();ch=getchar();while(ch!='E' && ch!='W' && ch!='S' && ch!='N')ch=getchar();
	    if(ch=='E'){
			x1=x+y;
			if(x1>w)y1=x1-w,x1=w;
			else y1=0;
			x2=x+d-y;
			if(x2>w)y2=d-x2+w,x2=w;
			else y2=d;
		}
		else if(ch=='W'){
		    x1=x-d+y;
		    if(x1<0)y1=d+x1,x1=0;
			else y1=d;
			x2=x-y;
		    if(x2<0)y2=-x2,x2=0;
			else y2=0;
		}
		else if(ch=='S'){
		    x1=x-y;
		    if(x1<0)y1=-x1,x1=0;
		    else y1=0;
		    x2=x+y;
		    if(x2>w)y2=x2-w,x2=w;
		    else y2=0;
		}
		else if(ch=='N'){
		    x1=x+d-y;
		    if(x1>w)y1=d-x1+w,x1=w;
		    else y1=d;
		    x2=x-d+y;
		    if(x2<0)y2=d+x2,x2=0;
		    else y2=d;
		}
		if(x1==0 || y1==d)s[i]=len-x1-y1;
		else s[i]=x1+y1;
		if(x2==0 || y2==d)t[i]=len-x2-y2;
		else t[i]=x2+y2;
		if(t[i]<s[i])t[i]+=len;
		s[i+n]=s[i]+len;
		t[i+n]=t[i]+len;
		p[i]=make_pair(t[i],s[i]);
		p[i+n]=make_pair(t[i+n],s[i+n]);
	}
	sort(p+1,p+1+n+n);
}
void solveit(){
	int ans=0;
    for(int i=1;i<=n;++i){
	    int tmp=0,lst=0;
	    for(int j=i;p[j].first<p[i].second+len;++j){
		    if(lst<p[j].second){
			    ++tmp;lst=p[j].first;
			}
		}
	    ans=max(ans,tmp);
	}
	printf("%d\n",ans);
}
int main(){
    init();
    solveit();
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值