Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1023 | Accepted: 337 |
Description
Input
Output
Sample Input
1 6 1 1 2 3 3 2 4 4 10 4 2 5
Sample Output
2
Source
二分+2-SAT可行性判断
题意:给你n个点,要你在这n个点上放一个正方形,点
只能在正方形的上边或下边的中点上,所有正方形大小一样,
不能重叠,求最大的正方形。。。
如果abs(s[i].x-s[j].x)>=r则可以随便放
如果 abs[s[i].x-s[j].y)<r;
如果abs(s[i].y-s[j].y)<r,如果s[i].y==s[i].y则要求一个放上面一个放下面。
否则只能是上面的点放上面,下面的点放下面。
如果r<=abs(s[i].y-s[j].y)<2*r,则除了上面的点放下方、下面的点放上方的情况都是可以的。
/* POJ 2296 二分+2-SAT可行性判断 题意:给你n个点,要你在这n个点上放一个正方形,点 只能在正方形的上边或下边的中点上,所有正方形大小一样, 不能重叠,求最大的正方形。。。 如果abs(s[i].x-s[j].x)>=r则可以随便放 如果 abs[s[i].x-s[j].y)<r; 如果abs(s[i].y-s[j].y)<r,如果s[i].y==s[i].y则要求一个放上面一个放下面。 否则只能是上面的点放上面,下面的点放下面。 如果r<=abs(s[i].y-s[j].y)<2*r,则除了上面的点放下方、下面的点放上方的情况都是可以的。 C++ 422ms 467K G++ 32ms */ #include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<math.h> using namespace std; const int MAXN=220; bool visit[MAXN]; queue<int>q1,q2; //vector建图方法很妙 vector<vector<int> >adj; //原图 //中间一定要加空格把两个'>'隔开 vector<vector<int> >radj;//逆图 vector<vector<int> >dag;//缩点后的逆向DAG图 int n,cnt; int id[MAXN],order[MAXN],ind[MAXN];//强连通分量,访问顺序,入度 void dfs(int u) { visit[u]=true; int i,len=adj[u].size(); for(i=0;i<len;i++) if(!visit[adj[u][i]]) dfs(adj[u][i]); order[cnt++]=u; } void rdfs(int u) { visit[u]=true; id[u]=cnt; int i,len=radj[u].size(); for(i=0;i<len;i++) if(!visit[radj[u][i]]) rdfs(radj[u][i]); } void korasaju() { int i; memset(visit,false,sizeof(visit)); for(cnt=0,i=0;i<2*n;i++) if(!visit[i]) dfs(i); memset(id,0,sizeof(id)); memset(visit,false,sizeof(visit)); for(cnt=0,i=2*n-1;i>=0;i--) if(!visit[order[i]]) { cnt++;//这个一定要放前面来 rdfs(order[i]); } } bool solvable() { for(int i=0;i<n;i++) if(id[2*i]==id[2*i+1]) return false; return true; } struct Point { int x,y; }s[MAXN]; int main() { int T; int left,right,mid; int ans; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&s[i].x,&s[i].y); left=0; right=80000; while(right-left>=0) { mid=(left+right)>>1; adj.assign(2*n,vector<int>()); radj.assign(2*n,vector<int>()); //2*i表示放上面的,2*i+1表示放下面 for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { if(abs(s[i].x-s[j].x)>=mid)continue;//没有限制 if(abs(s[i].y-s[j].y)<mid) { if(s[i].y==s[j].y)//一个上一个下 { adj[2*i].push_back(2*j+1); adj[2*j].push_back(2*i+1); adj[2*i+1].push_back(2*j); adj[2*j+1].push_back(2*i); radj[2*i].push_back(2*j+1); radj[2*j].push_back(2*i+1); radj[2*i+1].push_back(2*j); radj[2*j+1].push_back(2*i); } else if(s[i].y>s[j].y)//i放上面,j放下面 { adj[2*i+1].push_back(2*i); adj[2*j].push_back(2*j+1); radj[2*i].push_back(2*i+1); radj[2*j+1].push_back(2*j); } else { adj[2*i].push_back(2*i+1); adj[2*j+1].push_back(2*j); radj[2*i+1].push_back(2*i); radj[2*j].push_back(2*j+1); } } else if(abs(s[i].y-s[j].y)<2*mid)//上面的放下面和下面的放上面是不允许的 { if(s[i].y>s[j].y) { adj[2*i+1].push_back(2*j+1); adj[2*j].push_back(2*i); radj[2*j+1].push_back(2*i+1); radj[2*i].push_back(2*j); } else { adj[2*j+1].push_back(2*i+1); adj[2*i].push_back(2*j); radj[2*i+1].push_back(2*j+1); radj[2*j].push_back(2*i); } } } korasaju(); if(solvable()){ans=mid;left=mid+1;} else right=mid-1; } printf("%d\n",ans); } return 0; }