。。。
不是啊。
我acos一个1+2e-16它返回nan,这怎么调啊???
自己完美地solo完了整道题,结果没过,太可惜了(((
复杂度O(n)
考虑从头开始选,每选一条线段都会有对应的范围吧。这里范围的定义是『前n条线段组成的终点到原点的距离』
然后我们看一下终点是不是在区间里,
假设能到达,
我们定义ans[i]是前i条线段组成的终点到原点的距离
我们从终点倒着求,现在我们要调整第n条线段使得第n条线段的起点在前n-1条线段的可行区间里。
那么我们根据ans[n]求出来另一个可行区间,这两个区间一定有交,我们枚举一下四个端点即可确定ans[n-1],
然后余弦定理求旋转角。
递归n次。
这个acos还是第一次遇到。。。我人傻了。
#include <bits/stdc++.h>
using namespace std;
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;}
int cmp(db k1,db k2){return sign(k1-k2);}
struct point {
db x,y;
point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
point operator * (db k1) const{return (point){x*k1,y*k1};}
point operator / (db k1) const{return (point){x/k1,y/k1};}
point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
db abs(){return sqrt(x*x+y*y);}
void print(){printf("%.3f %.3f\n",x,y);}
point unit(){
db w=abs();
if(cmp(w,0)==0)return {0,0};
return (point){x/w,y/w};
}
db getw(){return atan2(y,x);}
};
db jiao(db a,db b,db c){
if(cmp(a,0)==0||cmp(b,0)==0)return 0;
db s = (a*a+b*b-c*c)/2/a/b;
if(cmp(s,1)==0)s=1;
else if(cmp(s,-1)==0)s=-1;
return acos(s);
}
point p[22],x;
int n;
db a[22],l[22],r[22],ans[22],delta[22],l2[22],r2[22];
bool can(db x,int i){return cmp(x,l[i])>=0&&cmp(x,r[i])<=0&&cmp(x,l2[i])>=0&&cmp(x,r2[i])<=0;}
void slove(int now){//在求第now个点
if(now<1)return;
//不妨对每一步求可行解
if(cmp(a[now+1],l2[now+1])>=1&&cmp(a[now+1],r2[now+1])<=0){
l2[now]=0;
}else if(cmp(a[now+1],l2[now+1])==-1){
l2[now]=l2[now+1]-a[now+1];
}else if(cmp(a[now+1],r2[now+1])==1){
l2[now]=a[now+1]-r2[now+1];
}
r2[now]=r2[now+1]+a[now+1];
db x=0;
if(can(l[now],now)){x=l[now];
}else if(can(r[now],now)){x=r[now];
}else if(can(l2[now],now)){x=l2[now];
}else if(can(r2[now],now)){x=r2[now];}
ans[now]=x;
l2[now]=ans[now],r2[now]=ans[now];
db del = jiao(ans[now],ans[now+1],a[now+1]);
delta[now] = del;//我要绕逆时针角度
slove(now-1);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
scanf("%lf%lf",&x.x,&x.y);
ans[n]=x.abs();
ans[1]=a[1];
l[1]=a[1],r[1]=a[1];
for(int i=2;i<=n;i++){
if(cmp(a[i],l[i-1])>=0&&cmp(a[i],r[i-1])<=0){
l[i]=0;
}else if(cmp(a[i],l[i-1])==-1){
l[i]=l[i-1]-a[i];
}else if(cmp(a[i],r[i-1])==1){
l[i]=a[i]-r[i-1];
}
r[i]=r[i-1]+a[i];
}
if(cmp(ans[n],r[n])>=1){
x = x.unit()*r[n];
if(x.abs()==0)x={r[n],0};
}else if(cmp(ans[n],l[n])<=0){
x = x.unit()*l[n];
if(x.abs()==0)x={l[n],0};
}
p[n]=x;ans[n]=x.abs();l2[n]=ans[n],r2[n]=ans[n];
delta[n]=x.getw();
slove(n-1);
for(int i=n-1;i>=1;i--)delta[i]+=delta[i+1];
for(int i=1;i<=n;i++){
point tmp = {ans[i],0};
tmp.turn(delta[i]).print();
}
}
/**
4
7 8 9 20
0 -34
2
10000 132576
-37 -9999
*/