题目: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; }