题意:
给一条折线,每一次操作把这条折线的所有线段变换成跟这条折线的相同形状,重复d次。问此时从头到尾走全长的f(0≤f≤1),将停在哪个点上。
题解:
首先计算出每次变换线段增长的倍数
k
,那么线段会增长
要注意每次变换后坐标需要旋转,这个预处理就好了。
#include<iostream>
#include<iomanip>
#include<cmath>
#include<iomanip>
#include<cstdio>
using namespace std;
int T,n,d;
double res,ratio,totlen,lenall,powRatio[15];
struct point{
double x,y;
point(double x=0,double y=0):x(x),y(y){}
friend inline point operator +(const point &a,const point &b){return point(a.x+b.x,a.y+b.y);}
friend inline point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}
inline double len()const{return sqrt(x*x+y*y);}
friend inline point operator *(const point &a,const double &o){return point(a.x*o,a.y*o);}
friend inline point operator /(const point &a,const double &o){return point(a.x/o,a.y/o);}
friend inline double operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;}
inline point rev(double theta){return point(x*cos(theta)-y*sin(theta),x*sin(theta)+y*cos(theta));}
friend inline double calc(const point &a,const point &b){
return acos((a.x*b.x+a.y*b.y)/(a.len()*b.len()))*(a*b>0?1:-1);;
}
}st,ls,to[150],p[150];
struct line{
point a,b;
line(point a,point b):a(a),b(b){}
};
double ang[150];
inline point dfs(line l,point s,int dnow,double theta,double t){
double nowtheta=0;
for(int i=1;i<n;i++){
double len=to[i].len()*t*powRatio[dnow];
if(len>res){
if(dnow)return dfs(line(s,s+to[i].rev(theta)*t),s,dnow-1,theta+ang[i],t*(to[i].len())/lenall);
else return s+to[i].rev(theta)/to[i].len()*res;
}
else res-=len,s=s+to[i].rev(theta)*t;
}
return s;
}
int main(){
cin>>T;
while(T--){
cin>>n;totlen=0;
cin>>st.x>>st.y;p[1]=ls=st;
for(int i=1;i<n;i++){
cin>>p[i+1].x>>p[i+1].y;
to[i]=p[i+1]-ls;ls=p[i+1];
totlen+=to[i].len();
}
ratio=totlen/(lenall=((ls-st).len()));
cin>>d>>res;d--;
powRatio[0]=1.0;
for(int i=1;i<n;i++)
ang[i]=calc((ls-st),to[i]);
for(int i=1;i<=d;i++)powRatio[i]=powRatio[i-1]*ratio;
res*=totlen*powRatio[d];
point q=dfs(line(p[1],p[n]),st,d,0,1);
printf("(%.10f,%.10f)\n",q.x,q.y);
}
}