日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU多校3 - 6798 Triangle Collision(几何+旋转坐标系)

發布時間:2024/4/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU多校3 - 6798 Triangle Collision(几何+旋转坐标系) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個等邊三角形的區域,再給出初始時一個質點的位置 ( x , y?) 和初始速度 ( vx , vy ) ,現在質點會不斷運動,當碰到三角形的內壁時會根據角度反彈,問小球第 k 次碰到三角形的內壁的時間

題目分析:k 非常大,肯定不能暴力去模擬每一次小球的運動,借用題解的一句話更好理解:

靈感來自用激光筆往鏡子中射入激光被多次反射。
人眼從激光筆的視角來看,光束并沒有被 “反射”,而是穿入了 “鏡子中的世界”。

將二維平面視為無窮大,大概就是這樣互相拼接而成的等邊三角形假設點 A 為起點,點 B 為一段時間后到達的位置,則線段 AB 穿過的三角形的邊數,就是質點碰撞三角形內壁的次數了

這樣一來,可以二分時間,然后去檢查線段穿過的次數與題目中給出 k 的關系,當然,計算穿過的邊數也是有技巧的,如果硬算投影的話應該也是可以的,只是比較麻煩,首先考慮如果只是計算穿過的藍色線段的數量,可以直接根據 y 的值稍加計算得到,同理,可以旋轉一下坐標系,這樣就能很方便的求出穿過黃色和紅色直線的條數了

借用一下大佬博客的圖片:https://blog.csdn.net/jk_chen_acmer/article/details/107641065

像上面一樣,每次逆時針旋轉 120 度即可

注意一下,因為我們在旋轉后,想要使得初始的三角形的三條邊位于 x 軸上,所以初始點 P 是圍繞著三角形的中心旋轉的,而速度向量是 V - O 構成的,換句話說,需要將點 V 和點 O 分別旋轉后再做減法得到向量(這樣操做或許比較麻煩,但個人看來是最容易理解的)

因為在進行上述旋轉后,有一個好處就是,初始時的點 P 的 y 坐標一定是大于 0 的,所以此時對于運動停止時的點 Q ,我們分兩種情況討論:

  • Q.y > 0:Q 和 P 位于 x 軸的同一側,此時答案為
  • Q.y < 0:Q 和 P 位于 x 軸的不同側,需要加上 y = 0 這條直線,此時答案為(因為 Q.y 是小于 0 的,所以需要減)
  • 代碼:

    #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;const double eps = 1e-8;const double pi = acos(-1.0);int sgn(double x){if(fabs(x) < eps)return 0;if(x < 0)return -1;else return 1; }struct Point{double x,y;Point(){}Point(double _x,double _y){x = _x;y = _y;}bool operator == (Point b)const{return sgn(y-b.y) == 0;}bool operator < (Point b)const{return sgn(y-b.y)<0;}Point operator -(const Point &b)const{return Point(x-b.x,y-b.y);}Point operator +(const Point &b)const{return Point(x+b.x,y+b.y);}Point operator *(const double &k)const{return Point(x*k,y*k);}//叉積double operator ^(const Point &b)const{return x*b.y - y*b.x;}//點積double operator *(const Point &b)const{return x*b.x + y*b.y;}//返回兩點的距離double distance(Point p){return hypot(x-p.x,y-p.y);}//`繞著p點逆時針旋轉angle`Point rotate(Point p,double angle){Point v = (*this) - p;double c = cos(angle), s = sin(angle);return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);} };double L,x,y,vx,vy,h;int k;Point P[4],Q[4],V[4],O[4],T;LL cal(double t,int i) {Point Q=P[i]+V[i]*t;if(sgn(Q.y)>=0)return (LL)floor(Q.y/h);elsereturn 1LL-(LL)ceil(Q.y/h); }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%lf%lf%lf%lf%lf%d",&L,&x,&y,&vx,&vy,&k);h=sqrt(3)*L/2.0;T=Point(0,h/3.0);//中心點O[1]=Point(0,0),O[2]=O[1].rotate(T,pi*2.0/3.0),O[3]=O[1].rotate(T,pi*4.0/3.0);//原點P[1]=Point(x,y),P[2]=P[1].rotate(T,pi*2.0/3.0),P[3]=P[1].rotate(T,pi*4.0/3.0);//初始點V[1]=Point(vx,vy),V[2]=V[1].rotate(T,pi*2.0/3.0),V[3]=V[1].rotate(T,pi*4.0/3.0);//速度向量for(int i=1;i<=3;i++)V[i]=V[i]-O[i];//得到速度向量double l=0,r=1e10,ans;while(fabs(l-r)>=1e-5){double mid=(l+r)*0.5;if(cal(mid,1)+cal(mid,2)+cal(mid,3)>=k){ans=mid;r=mid;}elsel=mid;}printf("%.10f\n",ans);}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的HDU多校3 - 6798 Triangle Collision(几何+旋转坐标系)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。