主页
搜索
最近更新
数据统计
申请密钥
批量保存
开发版网站(新前端)
系统公告
1
/
1
请查看完所有公告
P9141 解题报告
最后更新于 2025-08-27 19:32:49
作者
da_ke
分类
题解
题解
P9141
复制 Markdown
查看原文
转到新前端
删除文章
更新内容
P9141 解题报告 ```cpp #include <bits/stdc++.h> #define i64 long long #define rep(i,l,r) for(int i=(l);i<=(r);i++) #define fdn(i,r,l) for(int i=(r);i>=(l);i--) #define pii pair<int,int> using namespace std; typedef long long ll; typedef long double db; typedef __int128 i128; std::mt19937 rnd(std::chrono::steady_clock::now().time_since_epoch().count()); std::mt19937_64 rnd64(std::chrono::steady_clock::now().time_since_epoch().count()); // 写代码大忌: // 重复变量,重复循环变量。 // 解决这道题实数问题 const db e=1e-7; const db inf=1e9; bool feq(db a,db b){return fabs(a-b)<=e;} bool flt(db a,db b){return a<b&&!feq(a,b);} bool fgt(db a,db b){return a>b&&!feq(a,b);} bool fle(db a,db b){return a<b||feq(a,b);} bool fge(db a,db b){return a>b||feq(a,b);} db f_min(db a,db b){return fle(a,b)?a:b;} int to_int(db x) { double r=round(x); if(feq(r,x)) return static_cast<int>(r); else return inf; } // 实现 R^3 的一些基本运算。 struct Vec { db x,y,z; Vec() : x(0),y(0),z(0) {}; Vec(db _x,db _y,db _z) : x(_x),y(_y),z(_z) {}; db mol() { return sqrt(x*x+y*y+z*z); } db mol2() { return x*x+y*y+z*z; } Vec operator +(Vec b) { return Vec(x+b.x,y+b.y,z+b.z); } Vec operator -() { return Vec(-x,-y,-z); } Vec operator -(Vec b) { return Vec(x-b.x,y-b.y,z-b.z); } Vec operator *(db u) { return Vec(u*x,u*y,u*z); } Vec operator /(db u) { return Vec(x/u,y/u,z/u); } Vec unit_vec() { return *this/(*this).mol(); } bool is_zero() { return feq(x,0)&&feq(y,0)&&feq(z,0); } }; db dot(Vec a,Vec b) { return a.x*b.x+a.y*b.y+a.z*b.z; } Vec cross(Vec a,Vec b) { return Vec(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); } db angle(Vec a,Vec b) { return acos(max((db)-1.0,min(dot(a,b),(db)1.0))); } // 无人机 struct Plane { int id,from; Vec p,d,u; // 位置向量,方向向量,法向量 // l=u \times d 叉乘 // u,d,l 都是单位向量 db thetau,thetad,g,vm,Lx,Hy; bool crashed; int target; Vec flight_plan; bool is_in_sight(Plane x) { return fgt(dot(this->d,(x.p-this->p)),(db)0); } pair<db,db> Projection(Plane x) { Vec l=cross(this->u,this->d); Vec q=x.p-p; // 转换原点 db qx=dot(q,l),qy=dot(q,u); return make_pair(qx,qy); } bool is_in_ra(Plane x) { auto q=Projection(x); return fle(fabs(q.first),Lx)&&fle(fabs(q.second),Hy); } db calc_cost(Vec delta) { // 因为 p'-p=delta//d',所以,只需求出 delta 的单位向量 Vec d1=delta.unit_vec(); // 求 d 和 d1 构成的平面的单位法向量。 Vec n=cross(d1,d); // 特判 d//d1,此时 n=0 Vec l=cross(d,u); if(n.is_zero()) n=l; else { // 变为单位 n=n.unit_vec(); // 夹角必须为锐角,钝角化补。 if(dot(n,l)<0) n=-n; } // 滚转率,求 n,l 的夹角。 db ans1=(db)angle(n,l)/g; // +杆,-杆 db ans2; if(fge(dot(u,d1),0)) ans2=angle(d,d1)/thetau; else ans2=angle(d,d1)/thetad; // 直线飞行 db ans3=delta.mol()/vm; return ans1+ans2+ans3; } }; int n,T; vector<Plane> planes; struct Missile { }; inline void search_target(Plane& t) { if(t.crashed) return; int _l,_r; if(t.id<=n) _l=n+1,_r=2*n; else _l=1,_r=n; int _min=inf,minid=_l; bool can_find=0; rep(i,_l,_r) // 寻找敌机 { Plane& s=planes[i]; if(!s.crashed&&t.is_in_sight(s)) { can_find=1; break; } } if(!can_find) t.target=0; // 若本机视野内无敌方阵营无人机(简称“敌机”,下同),则本机无选定目标; if((!t.target)||(planes[t.target].crashed)||(!t.is_in_sight(planes[t.target]))) // 否则,若上一时刻本机选择的无人机仍位于本机视野内,则本机仍选定该目标; { /*否则,若存在至少一架敌机处于本机雷达扫描范围内, 则选取其中与本机距离最近的; 若与本机距离最近的敌机不唯一,则选取编号最小的。*/ bool can_find_ra=0; rep(i,_l,_r) { Plane& s=planes[i]; if(!s.crashed&&t.is_in_ra(s)) { can_find_ra=1; break; } } if(can_find_ra) { db mindis=inf,minid=0; rep(i,_l,_r) { Plane& s=planes[i]; if(!s.crashed&&t.is_in_ra(s)) { if( fle((s.p-t.p).mol2(),mindis) ) mindis=(s.p-t.p).mol2(),minid=i; } } t.target=minid; } else { /* 必须在视野内! 计算投影,Manhattan 最小*/ db mindis=inf,minid=0; rep(i,_l,_r) { Plane& s=planes[i]; if(!s.crashed&&t.is_in_sight(s)) { auto R=t.Projection(s); db dis=f_min( (db)fabs(R.first-t.Lx),(db)fabs(R.first+t.Lx) )+ f_min( (db)fabs(R.second-t.Hy),(db)fabs(R.second+t.Hy) ); if(dis<mindis) mindis=(s.p-t.p).mol2(),minid=i; } } t.target=minid; } } } inline void make_flight_plan(Plane& t) { if(t.crashed) return ; if(t.target) { Plane& s=planes[t.target]; // 枚举目标位置。 int can_find=0; int lim=floor(t.vm); // 减少代码复杂程度,保留筛选对象。 vector<Vec> step1; rep(i,-lim,lim) rep(j,-lim,lim) rep(k,-lim,lim) { Vec delta=Vec(i,j,k); if(delta.is_zero()) continue; Plane t1=t; t1.p=t.p+delta; bool _can_mv=1; // 判断能否合法位移到。 if(fgt(t.calc_cost(delta),1.0)) _can_mv=0; if(!t1.is_in_sight(s)) _can_mv=0; if(_can_mv) can_find++,step1.push_back(delta); } if(can_find) // 1.1 { // 取 ||p'-q|| 最小。 db mindis=inf; vector<Vec> step2; for(auto i:step1) // 从符合条件的选。 { Plane t1=t; t1.p=t.p+i; db dis=(t1.p-s.p).mol2(); if(flt(dis,mindis)) mindis=dis; } for(auto& i:step1) { Plane t1=t; t1.p=t.p+i; db dis=(t1.p-s.p).mol2(); if(feq(dis,mindis)) step2.push_back(i); } if(step2.size()==1) t.flight_plan=step2.front(); // 1.1.1 else { vector<Vec> step3; for(auto i:step2) { Plane t1=t; t1.p=t.p+i; if(t1.is_in_ra(s)) step3.push_back(i); } // 找出所有在投影范围内的位置。 if(step3.size()==1) t.flight_plan=step3.front(); else if(step3.size()>1) // 1.1.1.1 { db mindis3=inf; for(auto i:step3) { Plane t1=t; t1.p=t.p+i; auto [rx,ry]=t1.Projection(s); db dis3=rx*rx+ry*ry; mindis3=f_min(mindis3,dis3); } vector<tuple<db,db,db>> step4; for(auto i:step3) { Plane t1=t; t1.p=t.p+i; auto [rx,ry]=t1.Projection(s); db dis3=rx*rx+ry*ry; int _qx=to_int(t1.p.x); int _qy=to_int(t1.p.y); int _qz=to_int(t1.p.z); if(feq(mindis3,dis3)) step4.push_back(make_tuple(_qx,_qy,_qz)); } sort(step4.begin(),step4.end()); auto [x_1,y_1,z_1]=step4.front(); t.flight_plan=Vec(x_1,y_1,z_1); } else // 1.1.2 { sort(step2.begin(),step2.end(),[&](Vec _a,Vec _b) { }); } } // 1.1.2 } else // 1.2 { db mindis=inf; vector<Vec> step5; for(auto i:step1) { Vec q=t.p+i; mindis=f_min(mindis,(q-t.p-t.d*t.vm).mol2()); } for(auto i:step1) { Vec q=t.p+i; if((q-t.p-t.d*t.vm).mol2()==mindis) step5.push_back(q); } sort(step5.begin(),step5.end()); t.flight_plan=step5.front(); } } else { // 眼镜蛇机动。 auto t1=t; t1.p=t.p,t1.d=t.u,t1.u=-t.d; } } int main() { // #ifndef ONLINE_JUDGE // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); // #endif ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr); // 读入 cin>>n>>T; planes.resize(2*n+1); rep(i,1,2*n) { int id; if(i<=n) id=1; else id=2; Plane& t=planes[i]; t.id=i,t.target=0,t.crashed=0,t.from=id; cin>>t.p.x>>t.p.y>>t.p.z; cin>>t.d.x>>t.d.y>>t.d.z; cin>>t.u.x>>t.u.y>>t.u.z; cin>>t.thetau>>t.thetad>>t.g>>t.vm>>t.Lx>>t.Hy; // 导弹 cin>>??? } // 开始 mol // 1. 所有无人机选定目标,制定策略。 rep(i,1,2*n) search_target(planes[i]),make_flight_plan(planes[i]); // 2. 所有能发射导弹的无人机发射导弹; } ```
正在渲染内容...
点赞
0
收藏
0