您的位置:首页 > 其它

BZOJ3970 WF2013 G Map Tiles

2018-01-16 21:42 204 查看
想象一个框把这个多边形框住,如果知道这个框的左上角的确切位置就能知道答案。

可以发现,这个位置有如下4种情况:

1. 一个顶点在水平线上,一个顶点在竖直线上

2. 一个顶点在水平线上,一个网格点在多边形边上

3. 一个顶点在竖直线上,一个网格点在多边形边上

4. 两个网格点在多边形边上

这样理论的点数有O(102n2) 个,但是点去重后实际数量非常少。

现在的问题是如何快速计算网格数

使用扫描线,对于一块长为1的,可以把里面区间扫一下之类的,拿个二进制数记录是否visit过

#include<bits/stdc++.h>
#define maxm 500100
#define maxn 110
using namespace std;
typedef double ldb;
typedef long double Ldb;
const ldb eps=1e-7;
int inline dcmp(ldb x){
return fabs(x)<eps?0:(x<0?-1:1);
}
struct point{
ldb x,y;
point(){}
point(ldb x,ldb y):x(x),y(y){}
point operator+(const point& p)const{return point(x+p.x,y+p.y);}
point operator+=(const point& p){return *this=*this+p;}
point operator-(const point& p)const{return point(x-p.x,y-p.y);}
point operator-=(const point& p){return *this=*this-p;}
point operator%(const point& p)const{return point(x-floor(x/p.x)*p.x,y-floor(y/p.y)*p.y);}
point operator%=(const point& p){return *this=*this%p;}
bool operator<(const point& p)const{return x==p.x?x<p.x:y<p.y;}
bool operator!=(const point& p)const{return dcmp(x-p.x)||dcmp(y-p.y);}
bool operator==(const point& p)const{return !dcmp(x-p.x)&&!dcmp(y-p.y);}
void scan(){int a,b;scanf("%d%d",&a,&b);x=a,y=b;}
}wxhs[maxm],p[maxn],A[maxn];
int pd(ldb x,ldb L,ldb R){
//  printf("<%.3lf,%.3lf,%.3lf,%d>",x,L,R,dcmp(x-L)*dcmp(x-R)>0);
return dcmp(x-L)*dcmp(x-R)>0;
}
int getwei(int l,int r){
return ((1<<r-l+1)-1)<<l;
}
int getl(ldb a){
return (int)floor(a+eps);
}
int getr(ldb a){
if(dcmp(floor(a+eps)-a))return (int)floor(a+eps);
else return (int)(floor(a+eps))-1;
}
typedef pair<ldb,ldb> par;
int n,w,ans,h,tp,ptr;
ldb B[110];
par C[110];
int cal(){
int sum=0,ptr=0,tp=0;
for(int i=1;i<=n;++i)
B[++ptr]=A[i].x;
for(int i=1;i<=11;++i)
B[++ptr]=i;
sort(B+1,B+ptr+1);
int used=0,ptr2=0;
for(int i=1;i<=ptr;++i)if(i==1||dcmp(B[ptr2]-B[i]))B[++ptr2]=B[i];
ptr=ptr2;
for(int i=1,nxt=1;i<=ptr;++i){
for(int j=1;j<=n;++j)if(dcmp(A[j+1].x-A[j].x)){
if(pd(B[i],A[j].x,A[j+1].x))continue;
if(pd(B[i+1],A[j].x,A[j+1].x))continue;
ldb y=(Ldb)(A[j+1].y-A[j].y)*(B[i]-A[j].x)/(Ldb)(A[j+1].x-A[j].x)+A[j].y;
ldb ny=(Ldb)(A[j+1].y-A[j].y)*(B[i+1]-A[j].x)/(Ldb)(A[j+1].x-A[j].x)+A[j].y;
C[++tp]=par(min(ny,y),max(ny,y));
}
sort(C+1,C+tp+1);
if(tp%2!=0)exit(1);
for(int i=1;i<=tp;i+=2)
used|=getwei(getl(min(C[i].first,C[i].second)),getr(max(C[i+1].first,C[i+1].second)));
if(!dcmp(B[i+1]-nxt)){
sum+=__builtin_popcount(used);
nxt++,used=0;
}
tp=0;

}
return sum;
}
int main(){
scanf("%d%d%d",&n,&w,&h);
for(int i=1;i<=n;++i)p[i].scan();
p[n+1]=p[1];
//case 1:one in ver line;one in hor line ->n^2
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
wxhs[++tp]=point(p[i].x,p[j].y);
//case 2:one in a ver line;one grid vertex on an edge(not ver) ->n^2*m
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(dcmp(p[j].x-p[j+1].x))
for(int k=-10;k<=10;++k){
ldb nx=k*w+p[i].x;
if(pd(nx,p[j].x,p[j+1].x))continue;
ldb y=(p[j].y-p[j+1].y)*(nx-p[j].x)/(p[j].x-p[j+1].x)+p[j].y;
wxhs[++tp]=point(nx,y);
}
//case 3:one in a hor line;one grid vertex on an edge(not hor) ->n^2*m
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(dcmp(p[j].y-p[j+1].y))
for(int k=-10;k<=10;++k){
ldb ny=k*h+p[i].y;
if(pd(ny,p[j].y,p[j+1].y))continue;
ldb x=(p[j].x-p[j+1].x)*(ny-p[j].y)/(p[j].y-p[j+1].y)+p[j].x;
wxhs[++tp]=point(x,ny);
}
//case 4:both on an edge -> n^2m^2 solve equations
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
for(int k=-10;k<=10;++k)
for(int l=-10;l<=10;++l){
ldb A1=p[i+1].y-p[i].y;
ldb B1=p[i].x-p[i+1].x;
ldb C1=-p[i+1].y*p[i].x+p[i+1].x*p[i].y;
ldb A2=p[j+1].y-p[j].y;
ldb B2=p[j].x-p[j+1].x;
ldb C2=-p[j+1].y*p[j].x+p[j+1].x*p[j].y;
if(!dcmp(A1*B2-A2*B1))continue;
ldb K=A1*B2-A2*B1;
ldb x=(B1*A2*k*w+B1*B2*l*h+B1*C2-B2*C1)/K;
ldb y=-(k*w*A1*A2+B2*A1*l*h+C2*A1-C1*A2)/K;
if(dcmp(A1*x+B1*y+C1))printf("[%.7lf]",A1*x+B1*y+C1),exit(1);
if(dcmp(A2*(x+k*w)+B2*(y+l*h)+C2))exit(2);
if(pd(x,p[i].x,p[i+1].x))continue;
if(pd(x+k*w,p[j].x,p[j+1].x))continue;
wxhs[++tp]=point(x,y);
}
for(int i=1;i<=tp;++i)
wxhs[i]%=point(w,h);
sort(wxhs+1,wxhs+tp+1);
int ans=1<<30,tp2=0;
for(int i=1;i<=tp;++i)if(i==1||(wxhs[tp2]!=wxhs[i]))
wxhs[++tp2]=wxhs[i];
tp=tp2;
for(int i=1;i<=tp;++i){
ldb x=wxhs[i].x,y=wxhs[i].y;
ldb dx=1e20,dy=1e20;
for(int j=1;j<=n+1;++j){
A[j].x=(p[j].x-x)/w;
A[j].y=(p[j].y-y)/h;
dx=min(dx,floor(A[j].x+eps));
dy=min(dy,floor(A[j].y+eps));
}
for(int j=1;j<=n+1;++j)
A[j].x-=dx,A[j].y-=dy;
ans=min(ans,cal());
}
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: