题目大意:起重机有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; }
若有写的好不的地方,欢迎指出