您的位置:首页 > 其它

【例题】【二分答案+2-SAT】NKOJ3814 调整卫星

2016-10-18 21:34 337 查看
NKOJ3814 调整卫星

时间限制 : - MS 空间限制 : 165536 KB

评测说明 : 1000ms

问题描述

某国上空有 n 颗卫星,…。每颗卫星有一次调整的机会,方式是卫星可以向 y 轴正方向移 动或 y 轴负方向移动指定长度。现在请你给每个卫星发出指令,让卫星向正方向移动或是负 方向移动,使得最后卫星分布中最近的两颗卫星的距离最远。 请输出最近两颗卫星距离的平方。

输入格式

输入第一行为一个数 n,表示有 n 颗卫星。接

下来的 n 行描述了 n 颗卫星,每行三个整数分别表示卫星的坐标 x,y 和卫星可以移 动的距离。

输出格式

输出一个整数表示答案。

样例输入

3

1 6 4

2 6 3

1000 5 3

样例输出

50

提示

【样例解释】 三颗卫星,坐标分别为(1,6) (2,6) (1000,5),第 1 颗卫星可以向上或向 下移 4 个单位,第 2 颗卫星可以向上或向下移 3 个单位,第 3 颗卫星可以向上或向下移 3 个单位。那么最好的方案是一号卫星向上移,二号卫星向下移,三号卫星随意。或是一号卫 星向上移,二号卫星向下移,三号卫星随意。这样移动后最近的卫星为一号卫星和二号卫星, 距离的平方为 7*7+1*1=50

【数据范围】

30% n<=10,坐标绝对值与移动距离小于 100

60% n<=100,坐标绝对值与移动距离绝对值小于 1000

100% n<=1000,坐标绝对值与任意移动距离均在 32 位整数范围内,无论如何调整, 任意两颗卫星的距离均小于 2^31.

思路:

首先要读出题目意思是:每颗卫星必须移动,且只能向上或向下固定距离

出题人的意思是二分答案+2-SAT验证…..

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
#define ll long long
const int need=1006;

int n,nn;

//.................................................
struct fy{int a,b;} w[need<<1];

ll dis[need<<1][need<<1];
ll dis_(fy a,fy b)//x,y在int 范围内,dis在long long范围内
{
int x=a.a-b.a,y=a.b-b.b;
return (ll)x*x+(ll)y*y;
}
//.................................................
int fi[need<<1],tot_=1;
struct edge
{
int en,la;
edge(int a=0,int b=0){en=a,la=b;}
} ;
vector<edge> ve;
#define pb(a,b) push_back(edge(a,b))

void add(int a,int b)
{
tot_++;
ve.pb(b,fi[a]);
fi[a]=tot_;
}
//.................................................
int dfn[need<<1],low[need<<1],id[need<<1],visttime,scc;
int st[need<<1],top;
bool ins[need<<1];

void tarjan(int x)
{
dfn[x]=low[x]=++visttime;
st[++top]=x;ins[x]=true;
int y;
for(int t=fi[x];t;t=ve[t].la)
{
y=ve[t].en;
if(dfn[y]==0)
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(ins[y]) low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x])
{
scc++;
do{
y=st[top],top--;
ins[y]=false;
id[y]=scc;
}while(x!=y);
}
}

bool judge(ll a)
{
visttime=top=scc=0;
tot_=1;
for(int i=1;i<=nn;i++) dfn[i]=low[i]=ins[i]=id[i]=fi[i]=0;
ve.clear();
ve.resize(2);

for(int i=2,j;i<=nn;i++)
for(j=2;j<=nn;j++)
if(dis[i][j]<a&&i/2!=j/2) add(i,j^1);

for(int i=2;i<=nn;i++) if(dfn[i]==0) tarjan(i);

for(int i=1;i<=n;i++) if(id[i<<1]==id[(i<<1)^1]) return 0;
return 1;
}
//.................................................
int main()
{
scanf("%d",&n);
nn=n*2+1;
for(int i=1,a,b,c;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
w[i<<1].a=a,w[i<<1].b=b+c;
w[(i<<1)^1].a=a,w[(i<<1)^1].b=b-c;
}

ll l=0,r,mid;

for(int i=2,j;i<=nn;i++)
for(j=i+1;j<=nn;j++)
dis[i][j]=dis[j][i]=dis_(w[i],w[j]),r=max(r,dis[i][j]);

while(l<=r)
{
mid=(l+r)>>1;
if(judge(mid)) l=mid+1;
else r=mid-1;
}
printf("%I64d",r);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: