Bomb Game
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2696 Accepted Submission(s): 894
Robbie has cracked the game, and he has known all the candidate places of each round before the game starts. Now he wants to know the maximum score he can get with the optimal strategy.
2 1 1 1 -1 -1 -1 -1 1 2 1 1 -1 -1 1 -1 -1 1
1.41 1.00
思路:二分最小距离-2-sat 判断可行性,强连通缩点,判断a,a^1不矛盾就行了。
(a,b)矛盾则(a,b^1),(b,a^1)加边,不可盲目加双向边。
这题坑了我近7个小时,两个问题。
1:加了双向边
2:tarjan()有错 instack忘给退了。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int mm=200+9;
const double eps=1e-6;
class node
{
public:
double x,y;
} f[mm];
int n;
double dis[mm][mm];
int head[mm],stack[mm],top,cnt,edge,dex,dfn[mm],low[mm],e_to[mm];
int ver[mm*mm],next[mm*mm];
bool instack[mm];
void data()
{
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
dex=top=cnt=edge=0;
}
void add(int u,int v)
{ if(u==v)return;
ver[edge]=v;
next[edge]=head[u];
head[u]=edge++;
// ver[edge]=u;
//next[edge]=head[v];
//head[v]=edge++;
}
double get_dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void tarjan(int u)
{
dfn[u]=low[u]=++dex;
stack[top++]=u;
instack[u]=1;
int v;
for(int i=head[u]; ~i; i=next[i])
{
v=ver[i];
if(!dfn[v])
{
tarjan(v);
low[u]=low[u]<low[v]?low[u]:low[v];
}
else if(instack[v])
{
low[u]=low[u]<dfn[v]?low[u]:dfn[v];
}
}
if(dfn[u]==low[u])
{
++cnt;
do
{
v=stack[--top];
instack[v]=0;
e_to[v]=cnt;
}
while(v^u);
}
}
bool two_sat(double x)
{
for(int i=0; i<n; ++i)
for(int j=i+1; j<n; ++j)
if(j^i&&dis[i][j]<x)
{
add(i,j^1),add(j,i^1);
// add(j^1,i);add(i^1,j);
// printf("dis=%lf %d -> %d\n",dis[i][j],i,j);
//printf("%d %d\n %d %d\n",i,j^1,j,i^1);
}
for(int i=0; i<n; ++i)
if(!dfn[i])
tarjan(i);
// for(int i=0;i<n;++i)
// cout<<i<<" "<<e_to[i]<<endl;
for(int i=0; i<n; ++i)
if(e_to[i]==e_to[i^1])return 0;
return 1;
}
int main()
{ ///freopen("data.in","r",stdin);
while(~scanf("%d",&n))
{
for(int i=0; i<n; ++i)
scanf("%lf%lf%lf%lf",&f[i+i].x,&f[i+i].y,&f[i+i+1].x,&f[i+i+1].y);
n+=n;
for(int i=0; i<n; ++i)
for(int j=i+1; j<n; ++j)
dis[i][j]=get_dis(f[i],f[j]);
double l=0.0,r=1e9,mid;
while(r-l>eps)
{
data();
mid=(l+r)/2.0;
// mid=3.80;
// puts("......................................................");
// printf("%lf----\n",mid);
if(two_sat(mid*2.0))
{l=mid;}
else {r=mid;}
}
printf("%.2lf\n",(l+r)/2.0);
}
}
1034



被折叠的 条评论
为什么被折叠?



