poj3845 Fractal

Posted by kliopa10 on Fri, 01 May 2020 21:07:42 +0200

Main idea:

For a polyline, each operation transforms all line segments of the polyline into the same shape as the polyline, and repeats d times. Ask at which point the f (0 ≤ f ≤ 1) times of the whole length from the beginning to the end will stop.

Solutions:

Assuming that the length of the broken line is k times of the original, the length of the fractal with the depth of d (d-1 times of operation) is 1 times of the original kd − 1. If the length of the current line segment has exceeded the remaining length, the end point is determined to be on the current line segment, then kd − 2 recursion is used to determine the line where the end point of the next layer transformation is located.
It should be noted that the figure needs to be rotated and scaled after each transformation, so the deflection angle of each segment should be preprocessed.

ps: when the accuracy of this question card reaches explosion, there will be less double operation.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;

const int N=105;
const double eps=1e-8;
struct point
{
    double x,y;
    point(){}
    point(double _x,double _y):x(_x),y(_y){}
    inline friend point operator - (const point &a,const point &b)
    {return point(a.x-b.x,a.y-b.y);}
    inline friend point operator + (const point &a,const point &b)
    {return point(a.x+b.x,a.y+b.y);}
    inline friend point operator / (const point &a,const double &b)
    {return point(a.x/b,a.y/b);}
    inline friend point operator * (const point &a,const double &b)
    {return point(a.x*b,a.y*b);}
    inline friend double operator * (const point &a,const point &b)
    {return a.x*b.y-a.y*b.x;}
    inline double dis(){return sqrt(x*x+y*y);}
}p[N];
struct line
{
    point v;
    double len,ang,ratio;
    line(){}
    line(point st,point ed)
    {len=(ed-st).dis();v=ed-st;}
}l[N];
int T,n,d;
double k,f,rate,L;

double calc(point a,point b)
{
    return acos((a.x*b.x+a.y*b.y)/(a.dis()*b.dis()))*(a*b>0?1:-1);
}

point rotate(point a,double theta)
{
    return point(a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta));
}

void go(point s,double R,int dep,double theta,double ratio)
{
    for(int i=1;i<n;i++)
    {
        double len=l[i].len*ratio*R;
        if(L-len<eps)
        {
            if(dep)go(s,R/rate,--dep,theta+l[i].ang,ratio*l[i].ratio);
            else
            {
                s=s+rotate(l[i].v,theta)/l[i].len*L;
                printf("(%.10f,%.10f)\n",s.x,s.y);
            }
            return;
        }
        else L-=len,s=s+rotate(l[i].v,theta)*ratio;
    }
}

int main()
{
    //freopen("lx.in","r",stdin);
    //freopen("lx.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
        scanf("%d%lf",&d,&f);d--;
        k=0;
        for(int i=1;i<n;i++) 
        {
            k+=(p[i+1]-p[i]).dis();
            l[i]=line(p[i],p[i+1]);
            l[i].ratio=l[i].len/(p[n]-p[1]).dis();
            l[i].ang=calc(p[n]-p[1],p[i+1]-p[i]);
        }
        rate=k/(p[n]-p[1]).dis();
        double R=1; 
        for(int i=1;i<=d;i++)R*=rate;
        L=f*R*k;
        go(p[1],R,d,0,1);                                                                                                                            
    }
    return 0;
}

Topics: less