您的位置:首页 > 其它

[BZOJ 3553/3554/3562/3564/3565/3566][SHTSC/HBOI 2014]解题报告

2014-11-30 17:18 555 查看

Day1

Problem 1 信号增幅仪(BZOJ 3564)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3564

思路:如果裸着做会很麻烦,所以我们需要进行一个简单的预处理。和增幅仪的旋转角度相反,将所有点顺时针旋转a度,然后将所有点的横坐标缩小p倍。然后就可以套用最小圆覆盖的模板做了,这里我用的是随机增量法。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>

#define PI 3.14159265358979323846
#define MAXN 510000
#define EPS (1E-20)

using namespace std;

struct Point
{
double x,y;
Point(double xx=0,double yy=0)
{
x=xx;
y=yy;
}
Point operator-(Point a)
{
return Point(x-a.x,y-a.y);
}
Point operator+(Point a)
{
return Point(x+a.x,y+a.y);
}
double operator*(Point a)
{
return x*a.y-y*a.x;
}
Point operator*(double t)
{
return Point(x*t,y*t);
}
Point operator/(double t)
{
return Point(x/t,y/t);
}
Point rotate(double ang) //绕原点顺时针旋转ang度
{
return Point(x*cos(ang)+y*sin(ang),-x*sin(ang)+y*cos(ang));
}
Point verl()
{
return Point(-y,x);
}
}dots[MAXN];

int n;

int dcmp(double x) //x>0返回1,x<0返回-1,x==0返回0
{
if(fabs(x)<EPS) return 0;
if(x>EPS) return 1;
return -1;
}

double dist(Point a,Point b) //求点a到点b距离
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

Point cross(Point a,Point b,Point c,Point d) //求向量ab叉乘向量cd
{
double s1=(d-a)*(c-a);
double s2=(c-b)*(d-b);
return (a*s2+b*s1)/(s1+s2);
}

Point cal(Point A,Point B,Point C)
{
Point ret;
double a1=B.x-A.x,b1=B.y-A.y,c1=(a1*a1+b1*b1)/2;
double a2=C.x-A.x,b2=C.y-A.y,c2=(a2*a2+b2*b2)/2;
double d=a1*b2-a2*b1;
ret.x=A.x+(c1*b2-c2*b1)/d;
ret.y=A.y+(a1*c2-a2*c1)/d;
return ret;
}

int main()
{
double ang,scale;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&dots[i].x,&dots[i].y);
scanf("%lf%lf",&ang,&scale);
ang=ang/180*PI;
for(int i=1;i<=n;i++)
{
dots[i]=dots[i].rotate(ang);
dots[i].x/=scale;
}
double r=0; //r=三角形的外接圆半径
Point c=dots[1];
for(int i=2;i<=n;i++)
{
if(dist(dots[i],c)>r+EPS)
{
c=dots[i];
r=0;
for(int j=1;j<i;j++)
{
if(dist(dots[j],c)>r+EPS)
{
c=(dots[i]+dots[j])/2;
r=dist(dots[j],c);
for(int k=1;k<j;k++)
{
if(dist(dots[k],c)>r+EPS)
{
c=cal(dots[i],dots[j],dots[k]);
r=dist(dots[i],c);
}
}
}
}
}
}
printf("%.3lf\n",r);
return 0;
}


Problem 2 概率充电器(BZOJ 3566)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3566

思路:树形DP,首先我们需要知道一个概率的公式,对于两个相互独立的事件A、B,P(A+B)=P(A)+P(B)-P(AB)。每个点都给它们的所有儿子贡献了一部分概率,第一次DFS时,我们需要求出每个点u的每个儿子v的充电概率P'(v)=P(v)+[P(u)*p(edge)]-[P(u)*p(edge)]*P(v)。由于第一次DFS时会混进重复计算的概率(因为父亲节点给本节点的概率不能被算进本节点给儿子节点的概率),所以要再进行一次DFS,去除掉重复的概率。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>

#define MAXN 1001000
#define EPS (1E-6)

using namespace std;

struct edge
{
int u,v,next;
double p; //边的导电概率
}edges[MAXN];

int head[MAXN],nCount=0;
double pNode[MAXN]; //直接通电的概率
double f[MAXN];
double ans=0;

void AddEdge(int U,int V,double P)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].p=P;
edges[nCount].next=head[U];
head[U]=nCount;
}

void dfs1(int u,int fa) //从点u开始dfs,u的父亲是fa
{
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(v==fa) continue;
dfs1(v,u);
pNode[u]=pNode[u]+pNode[v]*edges[p].p-pNode[u]*edges[p].p*pNode[v];
}
}

bool dcmp(double a)
{
return fabs(a-0)<EPS;
}

void dfs2(int u,int fa)
{
ans+=f[u];
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(v==fa) continue;
double tmp=(1-pNode[v]*edges[p].p);
if(dcmp(tmp)) //tmp==0
f[v]=1.0;
else
{
double y=(double)(f[u]-pNode[v]*edges[p].p)/(double)(1-pNode[v]*edges[p].p);
f[v]=pNode[v]+y*edges[p].p-pNode[v]*y*edges[p].p;
}
dfs2(v,u);
}
}

int main()
{
int n;
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++)
{
int u,v,p;
scanf("%d%d%d",&u,&v,&p);
AddEdge(u,v,(double)p/(double)100);
AddEdge(v,u,(double)p/(double)100);
}
for(int i=1;i<=n;i++)
{
scanf("%lf",&pNode[i]);
pNode[i]/=100;
}
dfs1(1,-1);
f[1]=pNode[1];
dfs2(1,-1);
printf("%.6f\n",ans);
return 0;
}


Problem 3 超能粒子炮(BZOJ 3565)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3565

Day2

Problem 1 神奇化合物(BZOJ 3562)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3562

Problem 2 三叉神经树(BZOJ 3553)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3553

Problem 3 神秘金字塔(BZOJ 3554)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=3554


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: