ZOJ3234 Protect the King

题什么的都不用说了吧,直接切正题:给N个点,求能画出的不相交矩形数量最多。然后就直接一个一个的求凸包,知道剩下三个以下的点。就是答案了。

我用的水平序,搞一下就好了。

附代码:

View Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MaxN 2010
struct atp
{
int x,y;
}p[MaxN];
int s[MaxN],a[MaxN];
bool v[MaxN],use[MaxN];
int n,tot,ans;
bool cmp(atp a,atp b)
{
if (a.y<b.y) return true; else
if (a.y>b.y) return false; else
if (a.x<=b.x) return true; else return false;
}

long long cross(int i,int j,int k)
{
long long x1=p[j].x-p[i].x,
y1=p[j].y-p[i].y,
x2=p[k].x-p[i].x,
y2=p[k].y-p[i].y;
return x1*y2-x2*y1;
}

void work()
{
memset(v,0,sizeof(v));
int i=1,top=2,cnt=0;
while (use[i]) i++; s[1]=i++;
while (use[i]) i++; s[2]=i++;
for (;i<=n;i++) if (!use[i])
{
while (top>1 && cross(s[top-1],s[top],i)<0) top--;
s[++top]=i;
}
for (i=1;i<=top;i++)
{
a[++cnt]=s[i];
v[s[i]]=true;
}
i=n,top=2;
while (use[i]) i--;s[1]=i--;
while (use[i]) i--;s[2]=i--;
for (;i>=1;i--) if (!use[i])
{
while (top>1&&cross(s[top-1],s[top],i)<0) top--;
s[++top]=i;
}

for (i=1;i<=top;i++)
if (!v[s[i]]) a[++cnt]=s[i];

for (i=1;i<=cnt;i++) use[a[i]]=true;
tot-=cnt;
ans++;
}

int main()
{
freopen("in","r",stdin);
freopen("out","w",stdout);
while (scanf("%d",&n)!=EOF)
{
tot=n;ans=0;
for (int i=1;i<=n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
sort(p+1,p+n+1,cmp);
memset(use,false,sizeof(use));
while (tot>2) work();
printf("%d\n",ans);
}
return 0;
}

你可能感兴趣的:(ZOJ)