poj3845:Fractal(坐标旋转)

传送门

题意:
给一条折线,每一次操作把这条折线的所有线段变换成跟这条折线的相同形状,重复d次。问此时从头到尾走全长的f(0≤f≤1),将停在哪个点上。

题解:
首先计算出每次变换线段增长的倍数 k ,那么线段会增长kd若当前线段增长后已经超出了所剩余的长度,就相当于确定变换后的直线在当前线段上,那么递归 k1 确定下一次变换的直线。
要注意每次变换后坐标需要旋转,这个预处理就好了。

#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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值