zoukankan      html  css  js  c++  java
  • poj2991 Crane(线段树+集合)白书例题

    题目大意:起重机有n节,题目给出要调节的k节,每节调节成x度,求最后底部的起重机的坐标(最顶上的起点为(0,0))。

    分析:一开始我看白书,看不懂他那个向量旋转的坐标是怎么来的,翻了很多博客,才发现,是自己数学基础的遗漏(都怪自己高中没好好学T.T),向量旋转涉及到复数的概念和表达。

    首先复数表达式z=x+i*y=|z|*(cosx+i*sinx)(i²=-1),假设两个个复数分别为

    z1=x1+y1*i=r1*(cos(p1)+i*sin(p1))

    z2=x2+y2*i=r2*(cos(p2)+i*sin(p2))

    (r1=|z|,r2=|z|)

    z1*z2=r1*r2*(cos(p1+p2)+i*sin(p1+p2))

    由上面的结果可以知道两个向量乘积可以看作两个模的乘积,两个向量角度相加。

    由这结论可以得到一个向量(x,y),乘上旋转p1度模为1的复数(cos(p1)+i*sin(p1))

    (x+y*i)*(cos(p1)+i*sin(p1))=x*cos(p1)-y*sin(p1)+(y*cos(p1)+x*sin(p1))*i

    由此可得向量(x,y)旋转p1度后的向量为( x*cos(p1)-y*sin(p1),(y*cos(p1)+x*sin(p1)) )

    x'= x*cos(p1)-y*sin(p1),y'=y*cos(p1)+x*sin(p1)

    另外再说明一下,白书的某个节点的的向量表达上为:该点向量坐标=左儿子节点的向量+右儿子节点的向量(旋转的向量)

    这题让真的让我收益非凡

    下面附上代码

    #define debug
    #include<stdio.h>
    #include<math.h>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<string>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<functional>
    #include<iomanip>
    #include<map>
    #include<set>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    pair<ll,ll>PLL;
    pair<int,ll>Pil;
    const int INF = 0x3f3f3f3f;
    const double inf=1e8+100;
    const int maxn =(1<<15)-1;
    const int N = 1e4+10;
    const ll mod=1000007;
    const double eps=1e-8;
    const double g=10.0;
    const double PI=acos(-1.0);
    int n,c;
    int L[N];
    int S[N],A[N];
    double vx[maxn],vy[maxn],ang[maxn];
    double prv[maxn];
    
    void init(int k,int l,int r) {
    	ang[k]=vx[k]=0.0;
    	//
    	if(r-l==1) {
    		vy[k]=L[l];
    	} else {
    		int chl=2*k+1,chr=2*k+2;
    		init(chl,l,(r+l)/2);
    		init(chr,(r+l)/2,r);
    		vy[k]=vy[chl]+vy[chr];
    	}
    }
    
    void change(int s, double a,int v,int l,int r) {
    	if(s<=l)
    		return;
    	else if(s<r) {
    		int chl=2*v+1,chr=2*v+2;
    		int m=(r+l)/2;
    		change(s,a,chl,l,m);
    		change(s,a,chr,m,r);
    		if(s<=m)
    			ang[v]+=a;
    		double ss=sin(ang[v]),cc=cos(ang[v]);
    		vx[v]=vx[chl]+(cc*vx[chr]-ss*vy[chr]);
    		vy[v]=vy[chl]+(ss*vx[chr]+cc*vy[chr]);
    	}
    }
    
    void solve() {
    	int i,j,cnt=0;
    	while(~scanf("%d%d",&n,&c)) {
    		if(cnt++){
    			puts("");
    		}
    		for(i=0; i<n; i++) {
    		//	cin>>L[i];
    		scanf("%d",&L[i]);
    		}
    		for(i=0; i<c; i++) {
    		//	cin>>S[i]>>A[i];
    		scanf("%d%d",&S[i],&A[i]);
    		}
    		//
    		init(0,0,n);
    		for(i=1; i<n; i++) {
    			prv[i]=PI;
    		}
    		for(i=0; i<c; i++) {
    			int s=S[i];
    			double a=A[i]/180.0*PI;
    		//	cout<<s<<" "<<A[i]<<" "<<a<<endl;
    			change(s,a-prv[s],0,0,n);
    			prv[s]=a;
    		//	cout<<fixed<<setprecision(2)<<vx[0]<<" "<<vy[0]<<endl;
    			printf("%.2f %.2f
    ",vx[0],vy[0]);
    		}
    	}
    }
    
    
    int main() {
    //	ios_base::sync_with_stdio(false);
    #ifdef debug
    	freopen("in.txt", "r", stdin);
    //	freopen("out.txt","w",stdout);
    #endif
    //	cin.tie(0);
    //	cout.tie(0);
    	solve();
    	return 0;
    }
    

      若有写的好不的地方,欢迎指出

  • 相关阅读:
    LA 6439 Pasti Pas! Hash
    HDU 1067 Gap BFS+Hash
    POJ 3474 Gold Balanced Lineup Hash
    ZOJ 3802 Easy 2048 Again 状压DP
    Hihocoder #1044 状态压缩·一
    HDU 2522 & AOJ 441 & AOJ 364 关于小数和分数的转换
    HDU 2549 Sumset Hash+枚举
    POJ 1840 Eqs Hash + 中途相遇法
    HDU 2128 Tempter of the Bone II BFS
    POJ 3686 & 拆点&KM
  • 原文地址:https://www.cnblogs.com/visualVK/p/8468967.html
Copyright © 2011-2022 走看看