zoukankan      html  css  js  c++  java
  • [poj][3845][Fractal]

    题目:http://poj.org/problem?id=3845

    题意:给一条折线,d次分形后,求一点到初始点的距离与总长度之比刚好为 f (0<=f<=1)的位置。(一开始有点搞不明白,后来才确定就是把起始点和结束点缩放到每一条边的端点上)

    普通方法

    View Code
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    #define sqr(x) ((x)*(x))
    using namespace std;
    
    const int N = 110;
    const double eps = 1e-12;
    
    struct cpoint{
        double x, y;
        void get(){scanf("%lf%lf", &x, &y);}
        void put(){printf("(%.7f,%.7f)\n", x, y);}
    }cp[N];
    
    int dcmp(double x){
        return x<-eps?-1:(x>eps);
    }
    
    double cross(cpoint o, cpoint p, cpoint q){
        return (p.x-o.x)*(q.y-o.y)-(p.y-o.y)*(q.x-o.x);
    }
    
    double dot(cpoint o, cpoint p, cpoint q){
        return (p.x-o.x)*(q.x-o.x)+(p.y-o.y)*(q.y-o.y);
    }
    
    double dis(cpoint p, cpoint q){
        return sqrt(sqr(p.x-q.x)+sqr(p.y-q.y));
    }
    
    double angle(cpoint o, cpoint p, cpoint q){
        double cr=cross(o,p,q), dt=dot(o,p,q);
        if (dcmp(cr)==0) cr=0;
        if (dcmp(dt)==0) dt=0;
        return atan2(cr,dt);
    }
    
    cpoint rotating(cpoint v,cpoint o,double ang,double scale){
        double c=scale*cos(ang), s=scale*sin(ang);
        v.x -= o.x, v.y -= o.y;
        o.x += v.x*c - v.y*s;
        o.y += v.x*s + v.y*c;
        return o;
    }
    
    int n, d;
    double f, g[N];
    
    void solve(){
        double tlen=0, res=0, ang, dx, dy, s;
        for (int i=1; i<n; i++)
            tlen += dis(cp[i],cp[i-1]);
        for (int i=0; i<n; i++)
            g[i]=res/tlen, res+=dis(cp[i],cp[i+1]);
        cpoint tmp;
        int t;
        for (int i=1; i<d; i++){
            t = 0;
            while (t<n&&dcmp(g[t]-f)<0)t++;
            if (dcmp(g[t]-f)==0){
                cp[t].put(); return;
            }
            dx = cp[t-1].x - cp[0].x;
            dy = cp[t-1].y - cp[0].y;
            tmp.x = cp[n-1].x + dx;
            tmp.y = cp[n-1].y + dy;
            ang = angle(cp[t-1],tmp,cp[t]);
            s = dis(cp[t],cp[t-1])/dis(cp[n-1],cp[0]);
            for (int j=1; j<n; j++)
                cp[j]=rotating(cp[j],cp[0],ang,s);
            for (int j=0; j<n; j++)
                cp[j].x += dx, cp[j].y += dy;
            f = (f-g[t-1])/(g[t]-g[t-1]);
        }
        t = 0;
        while (t<n&&dcmp(g[t]-f)<0)t++;
        if (dcmp(g[t]-f)==0){
            cp[t].put(); return ;
        }
        f = (f-g[t-1])/(g[t]-g[t-1]);
        dx = cp[t-1].x + (cp[t].x - cp[t-1].x) * f;
        dy = cp[t-1].y + (cp[t].y - cp[t-1].y) * f;
        printf("(%.7lf,%.7lf)\n", dx, dy);
    }
    
    int main(){
        //freopen("D:/a.txt", "r", stdin);
        int T;
        scanf("%d", &T);
        while (T--){
            scanf("%d", &n);
            for (int i=0; i<n; i++)
                cp[i].get();
            scanf("%d%lf", &d, &f);
            solve();
        }
        return 0;
    }

    复数A * B = C的几何意义是C的幅角为A和B的幅角之和,C的模为A的模和B的模的积。

    有时候角度向量转换什么的比较麻烦,利用复数更容易写一些,向量V按照向量A变换向量B后的结果就是V * B / A;

    View Code
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 110;
    const double eps = 1e-12;
    
    int dcmp(double x){
        return x<-eps?-1:(x>eps);
    }
    
    struct cpoint{
        double x, y;
        cpoint(){};
        cpoint(double x,double y):x(x),y(y){}
        void get() { scanf("%lf%lf", &x, &y); }
        void put() { printf("(%.7f,%.7f)\n", x, y); }
    }cp[N];
    
    struct Complex{
        double r, v;
        Complex(){}
        Complex(cpoint c){r=c.x,v=c.y;}
        Complex(double r,double v):r(r),v(v){}
        Complex operator + (const Complex& a)const{
            return Complex(r+a.r,v+a.v);
        }
        Complex operator - (const Complex& a)const{
            return Complex(r-a.r,v-a.v);
        }
        Complex operator * (const Complex& a)const{
            return Complex(r*a.r-v*a.v,v*a.r+r*a.v);
        }
        Complex operator / (const Complex& a)const{
            double R = a.r*a.r+a.v*a.v;
            return Complex((r*a.r+v*a.v)/R,(v*a.r-r*a.v)/R);
        }
    };
    
    struct cvector{
        cpoint s;
        Complex v;
        cvector(){}
        cvector(cpoint s,Complex v):s(s),v(v){}
    }vec[N], tmp;
    
    double dis(cpoint p, cpoint q){
        return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
    }
    
    cpoint trans(Complex c){
        return cpoint(c.r,c.v);
    }
    
    double g[N];       //记录每段的比率
    
    void solve(cpoint cp[], int n, int d, double f){
        int t; double len = 0, res = 0, x, y;
        for (int i=0; i<n; i++){
            vec[i]=cvector(cp[i],Complex(cp[i])-Complex(cp[0]));
            if (i) len+=dis(cp[i],cp[i-1]);
        }
        for (int i=0; i<=n; i++)
            g[i] = res / len, res += dis(cp[i],cp[i+1]);
        for (int i=1; i<d; i++){
            t = 0;
            while (t<n&&dcmp(g[t]-f)<0)t++;
            if (dcmp(g[t]-f)==0){
                vec[t].s.put(); return ;
            }
            tmp.v = vec[t].v - vec[t-1].v;
            vec[0].s = vec[t-1].s;
            for (int j=1; j<n; j++){
                vec[j].v = vec[j].v * tmp.v / vec[n-1].v;  //利用复数进行变换
                vec[j].s = trans(vec[j].v+Complex(vec[0].s));
            }
            f = (f-g[t-1])/(g[t]-g[t-1]);
        }
        t = 0;
        while (t<n&&dcmp(g[t]-f)<0)t++;
        if (dcmp(g[t]-f)==0){
            vec[t].s.put(); return ;
        }
        f = (f-g[t-1])/(g[t]-g[t-1]);
        x = vec[t-1].s.x+(vec[t].s.x-vec[t-1].s.x)*f;
        y = vec[t-1].s.y+(vec[t].s.y-vec[t-1].s.y)*f;
        cpoint(x,y).put();
    }
    
    int main(){
        //freopen("D:/a.txt", "r", stdin);
        int n, d, T;
        double f;
        scanf("%d", &T);
        while (T--){
            scanf("%d", &n);
            for (int i=0; i<n; i++)
                cp[i].get();
            scanf("%d%lf", &d, &f);
            solve(cp,n,d,f);
        }
        return 0;
    }
  • 相关阅读:
    June 26th 2017 Week 26th Monday
    June 25th 2017 Week 26th Sunday
    June 24th 2017 Week 25th Saturday
    June 23rd 2017 Week 25th Friday
    June 22nd 2017 Week 25th Thursday
    2018最佳网页设计:就是要你灵感爆棚!!!
    图片素材类Web原型制作分享-Pexels
    想要打动HR的心,UX设计师求职信究竟应该怎么写?
    【UXPA大赛企业专访】Mockplus:“设计替代开发”将成为现实
    2018年最好的医疗网站设计及配色赏析
  • 原文地址:https://www.cnblogs.com/nigel0913/p/2603108.html
Copyright © 2011-2022 走看看