2017-2018 ACM-ICPC East Central North America Regional Contest (ECNA 2017)部分题解
计划补J,B,I。
J题是一道简单的模拟题,但是训练的时候还是WA了。
分类一定要分清楚,不能没想清楚就上机,越上越乱。
J题代码
// 2020-09-08 20:56:35.545006
#include <bits/stdc++.h>
using namespace std;
int tim[50],rest[50],usage[50];
int a[50],b[50];
int main(){
int n=10;
for (int i=1; i<=n; ++i) scanf("%d%d",&a[i],&b[i]);
for (int i=n+1; i<=3*n; ++i){
a[i]=a[(i-1)%n+1];
b[i]=b[(i-1)%n+1];
}
for (int i=1; i<=n; ++i){
scanf("%d%d%d",&usage[i],&rest[i],&tim[i]);
}
int nowtime=0;
for (int i=1; i<=3*n; ++i){
int id=(i-1)%n+1;
//cerr<<"tim"<<tim[id]<<endl;
//case 1
if (nowtime<tim[id]){
tim[id]=max(nowtime+a[id],tim[id]);
nowtime+=a[id]+b[id];
}
else if ((nowtime-tim[id])%(usage[id]+rest[id])<usage[id]){
int tmp=(nowtime-tim[id])/(usage[id]+rest[id])*(usage[id]+rest[id])+tim[id];
tim[id]=tmp+usage[id]+rest[id];
tim[id]=max(tim[id],tmp+usage[id]+a[id]);
nowtime=tmp+usage[id]+a[id]+b[id];
}
else{
int tmp=(nowtime-tim[id])/(usage[id]+rest[id])*(usage[id]+rest[id])+tim[id];
tim[id]=tmp+usage[id]+rest[id];
tim[id]=max(tim[id],nowtime+a[id]);
nowtime+=a[id]+b[id];
}
}
cout<<nowtime-b[n]<<'\n';
}
B题是一道圆凸包题,做法就是找到最右边的圆,一定在凸包上,然后求出所有公切线,逐个旋转求出整个凸包,注意重圆和包含关系的处理
包含要去掉因为包含的圆算不了公切线。
代码
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
double laangl;
struct point{
double x,y;
point(){
}
point(double x,double y):x(x),y(y){
}
bool operator !=(const point& _) const{
return x!=_.x||y!=_.y;
}
};
const double ang=0.3214324;
const double eps=1e-7;
point rotate(point x){
return point(x.x*cos(ang)-x.y*sin(ang),x.x*sin(ang)+x.y*cos(ang));
}
double sqr(double x){
return x*x;
}
double dis(point x,point y){
return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y));
}
double dis(double r,point x,point y){
//cerr<<"X"<<x.x<<" "<<x.y<<endl;
//cerr<<"Y"<<y.x<<" "<<y.y<<endl;
double angl=asin(dis(x,y)/2/r);
//cerr<<"angl"<<angl<<" "<<dis(x,y)/2/r<<endl;
return angl*2*r;
}
double fix(double x){
while (x>=2*pi) x-=2*pi;
while (x<0) x+=2*pi;
return x;
}
struct line{
point o;
double ang;
point drive(double x){
return point(o.x+cos(ang)*x,o.y+sin(ang)*x);
}
line(point o,double ang):o(o),ang(ang){
}
void rotate(double x){
ang=fix(ang+x);
}
bool operator <(const line &_) const{
double x=ang,y=_.ang;
x=fix(x-laangl);
y=fix(y-laangl);
if (abs(x-y)<eps) return 0;
return x<y;
}
};
const int N=210;
struct circle{
point o;
double r;
pair<line,double> operator &(const circle &_) const{
double dist=dis(o,_.o);
double dr=_.r-r;
double len=sqrt(sqr(dist)-sqr(dr));
double angl=acos(dr/dist);
double angl2=fix(pi/2-angl);
line t(o,fix(atan2(_.o.y-o.y,_.o.x-o.x)));
t.rotate(-angl2);
line l=t;
l.rotate(-pi/2);
point tmp=l.drive(r);
return make_pair(line(tmp,t.ang),len);
}
bool contain(const circle &_) const{
return r-_.r+eps>=dis(o,_.o);
}
}a[N];
int n;
bool ban[N];
void QBH(){
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
if (i!=j&&a[i].contain(a[j])) ban[j]=1;
int cnt=0;
for (int i=1; i<=n; ++i) if (!ban[i]) a[++cnt]=a[i];
n=cnt;
}
double ans;
const point EMPTY=point(-2344,3455);
point la[N];
void solve(){
QBH();
//cerr<<n<<endl;
if (n<=1){
ans=2*pi*a[1].r;
return;
}
int mx=1;
for (int i=1; i<=n; ++i) if (a[i].r+a[i].o.x>a[mx].r+a[mx].o.x) mx=i;
//cerr<<"MX"<<mx<<endl;
int now=mx;
laangl=0;
for (int i=1; i<=n; ++i) la[i]=EMPTY;
while (1){
//cerr<<"now"<<now<<" "<<ans<<endl;
vector<pair<pair<line,double>,int> > g;
for (int i=1; i<=n; ++i) if (i!=now) g.push_back(make_pair(a[now]&a[i],i));
sort(g.begin(),g.end());
line tmp=g[0].first.first;
laangl=tmp.ang;
ans+=g[0].first.second;
int nxt=g[0].second;
if (la[now]!=EMPTY){
//cerr<<"HU"<<now<<endl;
ans+=dis(a[now].r,la[now],tmp.o);
la[now]=EMPTY;
//cerr<<dis(a[now].r,la[now],tmp.o)<<endl;
}
else la[now]=tmp.o;
if (la[nxt]!=EMPTY){
//cerr<<"HU"<<nxt<<endl;
ans+=dis(a[nxt].r,la[nxt],tmp.drive(g[0].first.second));
la[nxt]=EMPTY;
//cerr<<dis(a[nxt].r,la[nxt],tmp.drive(g[0].first.second))<<endl;
}
else la[nxt]=tmp.drive(g[0].first.second);
now=nxt;
if (now==mx) return;
}
}
int main(){
scanf("%d",&n);
for (int i=1; i<=n; ++i){
scanf("%lf%lf%lf",&a[i].o.x,&a[i].o.y,&a[i].r);
a[i].r+=10;
}
solve();
cout<<fixed<<setprecision(10)<<ans;
}