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;
    }
  • 相关阅读:
    HTTP请求返回状态码详解
    C#-MVC开发微信应用(1)--开始使用微信接口
    码源中国.gitignore忽略文件配置
    Windows Server 2008 R2 下配置证书服务器和HTTPS方式访问网站
    架设证书服务器 及 让IIS启用HTTPS服务
    css设置图片的透明度
    页面通过打开设备判断跳转的链接页面
    sql语句修改字段长度
    【C#】时间戳转换
    C# Linq 交集、并集、差集、去重
  • 原文地址:https://www.cnblogs.com/nigel0913/p/2603108.html
Copyright © 2011-2022 走看看