题意:给你n个点,要你在这n个点上放一个正方形,点只能在正方形的上边或下边的中点上,所有正方形大小一样,
不能重叠,求最大的正方形。
经典的题目,找约束关系要经过一些讨论。
//320 KB 16 ms #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 222; int n; struct node { int x,y; }poi[N]; struct edge { int v,next; }es[N*N]; int head[N],cnt; inline void add_edge(int u,int v) { es[cnt].v=v; es[cnt].next=head[u]; head[u]=cnt++; } int dfn[N],low[N],sta[N],top,tmp[N]; int index; void tarjan(int u) { dfn[u]=low[u]=++index; sta[++top]=u; tmp[u]=1; for(int i=head[u];~i;i=es[i].next) { int v=es[i].v; if(tmp[v]==0) tarjan(v); if(tmp[v]==1) low[u]=min(low[u],low[v]); } if(dfn[u]==low[u]) { do { int v=sta[top]; low[v]=low[u]; tmp[v]=2; }while(sta[top--]!=u); } } void init() { memset(head,-1,sizeof(head)); cnt=index=top=0; memset(dfn,0,sizeof(dfn)); memset(tmp,0,sizeof(tmp)); } bool ok(int r) { init(); for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { int u=i<<1,v=j<<1; if(abs(poi[i].x-poi[j].x)>=r) continue; else { int dy=abs(poi[i].y-poi[j].y); if(dy>=2*r) continue; else if(dy<2*r&&dy>=r) { if(poi[i].y>poi[j].y) add_edge(u^1,v^1),add_edge(v,u); else add_edge(u,v),add_edge(v^1,u^1); } else if(dy<r) { if(poi[i].y>poi[j].y) add_edge(u^1,u),add_edge(v,v^1); else if(poi[i].y<poi[j].y)add_edge(u,u^1),add_edge(v^1,v); else add_edge(u,v^1),add_edge(u^1,v),add_edge(v,u^1),add_edge(v^1,u); } } } for(int i=0;i<2*n;i++) if(dfn[i]==0) tarjan(i); for(int i=0;i<2*n;i++) if(low[i]==low[i^1]) return false; return true; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&poi[i].x,&poi[i].y); int lb=0,ub=100001; while(ub-lb>1) { int mid=(ub+lb)>>1; if(ok(mid)) lb=mid; else ub=mid; } printf("%d\n",lb); } return 0; }
时间: 2024-10-11 10:37:34