当前位置: 首页 > news >正文

P10801 [CEOI 2024] 海战

洛谷

题目要求找到哪些没有撞的。

考虑如何计算两个战舰是否会相撞。

如果两个方向分别向南北方向那么需要满足 \(x\) 坐标相等。

两个相遇时消耗的时间为两个的 \(y\) 坐标差值的一半(简单的相遇问题)。

东西方向同理可得。

然后考虑如果一个向北,一个向东,那么怎么判断是否会相遇。

我们先假设相撞的点为 \((x,y)\),经过的时间为 \(t\)

那么向北原本处于 \((x,y+t)\),向东的原本处于 \((x-t,y)\)

那么不难发现,我们需要保证这两个点的横坐标纵坐标差相等,并且方向要正确。

移项发现需要满足 \(y-x\) 的值相等时才有机会相撞。

其它的也用类似的方法推理即可。

那么我们把所有相撞方式分为 \(6\) 种,然后把有机会相撞的都给塞到一个 set 或者链表中。

按照横坐标或者纵坐标的值排序,显然相邻的两个更快相撞,并且如果两个无法相撞,那么两个可以看作两个需要反方向移动才能撞到,那么自然不用考虑越过这两个的点相撞。

判断能否相撞有直接枚举所有情况判断的笨方法,但实际上也可以改一下时间计算方法,如果计算出是负数或者方向相等则不会相撞,这样大概可以简化代码。

那么我们判断每个相邻的能否相撞,如果是,那么就加入一个小根堆中,每次把最小的取出来,进行修改即可。

注意多个撞到一起的情况也要考虑。

代码具体实现看代码和注释。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){char c=getchar();int x=0;bool f=0;while(c>'9'||c<'0'){if(c=='-')f=1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();if(f)return -x;return x;
}
int n,x[200005],y[200005],d[200005],vis[200005],id[6];
char op[3];
map<int,int> mp[6];
struct P{int v,x;bool friend operator<(P a,P b){return a.v<b.v;}P(int a,int b){v=a,x=b;}
};
set<P> s[6][200005];
void add(int op,int x,int v,int p){//加入set if(!mp[op][x])mp[op][x]=++id[op];s[op][mp[op][x]].insert({v,p});
}
void solve(int p,int x,int y,char op){if(op=='N'){d[p]=0;add(0,x,y,p),add(2,y-x,x,p),add(3,y+x,x,p);}if(op=='S'){d[p]=1;add(0,x,y,p),add(4,y+x,x,p),add(5,y-x,x,p);}if(op=='E'){d[p]=2;add(1,y,x,p),add(2,y-x,x,p),add(4,y+x,x,p);}if(op=='W'){d[p]=3;add(1,y,x,p),add(3,y+x,x,p),add(5,y-x,x,p);}
}
struct Q{int dis;P x,y;bool friend operator<(Q a,Q b){return a.dis>b.dis;}
};
priority_queue<Q> q;
int calc(int a,int b){//求时间 if(x[a]==x[b])return abs(y[a]-y[b])+1>>1;if(y[a]==y[b])return abs(x[a]-x[b])+1>>1;return abs(x[a]-x[b]);
}
bool check(int a,int b){//判断同一组中是否可以相撞(写的好像比较复杂,但也很无脑) if(d[a]==d[b])return false;if(d[a]==0&&d[b]==1&&y[a]>y[b])return true;if(d[a]==0&&d[b]==2&&y[a]>y[b])return true;if(d[a]==0&&d[b]==3&&y[a]>y[b])return true;if(d[a]==1&&d[b]==2&&y[a]<y[b])return true;if(d[a]==1&&d[b]==3&&y[a]<y[b])return true;if(d[a]==2&&d[b]==3&&x[a]<x[b])return true;swap(a,b);if(d[a]==0&&d[b]==1&&y[a]>y[b])return true;if(d[a]==0&&d[b]==2&&y[a]>y[b])return true;if(d[a]==0&&d[b]==3&&y[a]>y[b])return true;if(d[a]==1&&d[b]==2&&y[a]<y[b])return true;if(d[a]==1&&d[b]==3&&y[a]<y[b])return true;if(d[a]==2&&d[b]==3&&x[a]<x[b])return true;return false;
}
void solve2(int p){for(int j=1;j<=id[p];j++){int la=0;P tmp={0,0};for(P u:s[p][j]){if(la){if(check(la,u.x))q.push({calc(la,u.x),u,tmp});}la=u.x;tmp=u;}}
}
void del(int p,int w,P x){//删除并且把隔开的加入 w=mp[p][w];auto it=s[p][w].find(x);if(it==s[p][w].end())return;auto it2=it;it2++;if(it!=s[p][w].begin()&&it2!=s[p][w].end()){it--;if(check(it->x,it2->x))q.push({calc(it->x,it2->x),*it,*it2});}s[p][w].erase(x);
}
void Del(int p){if(d[p]==0)del(0,x[p],{y[p],p}),del(2,y[p]-x[p],{x[p],p}),del(3,y[p]+x[p],{x[p],p});if(d[p]==1)del(0,x[p],{y[p],p}),del(4,y[p]+x[p],{x[p],p}),del(5,y[p]-x[p],{x[p],p});if(d[p]==2)del(1,y[p],{x[p],p}),del(2,y[p]-x[p],{x[p],p}),del(4,y[p]+x[p],{x[p],p});if(d[p]==3)del(1,y[p],{x[p],p}),del(3,y[p]+x[p],{x[p],p}),del(5,y[p]-x[p],{x[p],p});
}
signed main(){n=read();for(int i=1;i<=n;i++){x[i]=read(),y[i]=read();scanf("%s",op);solve(i,x[i],y[i],op[0]);//加入对应的组 }for(int i=0;i<6;i++)solve2(i);//把相邻值加入小根堆 while(!q.empty()){Q u=q.top();q.pop();int x=u.x.x,y=u.y.x;if(vis[x]&&vis[x]<u.dis||vis[y]&&vis[y]<u.dis)continue;vis[x]=vis[y]=u.dis;Del(x),Del(y); }for(int i=1;i<=n;i++)if(!vis[i])printf("%lld\n",i);return 0;
}
/*
0 N S x
1 E W y
2 N E y-x
3 N W y+x
4 S E y+x
5 S W y-x
全部按照权值丢进set
计算方向不同的相邻船需要多少时间
丢进优先队列跑 
然后开始赤石 
*/
http://www.jsqmd.com/news/330533/

相关文章:

  • 三菱Q系列PLC大型自动化生产线程序案例分享
  • 探索工频UPS逆变器控制板的宝藏世界
  • FastAPI系列(18):ORM查询操作
  • 在光学与电磁领域中的多元技术探索与实践
  • 电动汽车集群优化:Matlab 与 Yalmip 的奇妙结合
  • 2026降AI率指南:10款论文降ai工具红黑榜!亲测哪个免费降ai率工具不“智障”?
  • MATLAB程序实现排列熵算法:含详细注释版本
  • 使用 Rust 与 Tokio 构建高性能异步微服务:从零到生产部署实战指南
  • devtest-20260201 - devtest
  • 单相七电平级联逆变器开环仿真之旅(MATLAB/Simulink 实现)
  • Day26焦点事件
  • Go语言并发模式详解:从Goroutine到Channel最佳实践
  • 污水处理项目:西门子S7 - 300PLC与TP900触摸屏仿真T125实战
  • Redis深度优化:如何通过数据结构设计提升缓存命中率
  • 2026年1月靠谱OMO模式数字经济电商平台推荐排行榜,数字化电子商务,OMO模式数字经济电商平台排行榜单
  • 基于Java技术的大学生跑腿系统的设计与开发 开题报告
  • Matlab法诺共振拟合与Q因子计算:探索微观世界的奇妙工具
  • 探索PEMFC质子交换膜燃料电池模型:从密歇根大学模型到自主搭建
  • 部署安装 K8s 为什么要关闭 swap 分区?
  • AT_agc040_c Neither AB nor BA
  • AI原生应用领域推理能力的实时性优化
  • 新能源锂电池项目欧姆龙 NJ 程序实战分享
  • Go语言并发模式解析:channel与goroutine最佳实践
  • Clawdbot安装教程:从零开始到接入飞书
  • 基于MATLAB与CNN的语音信号分类探索
  • 老年人能力评估系统开发Day8
  • MATLAB代码:考虑电动汽车有序充放电的机组组合和最优潮流 关键词:电动汽车 MILP 最优...
  • GPUHammer:首个针对NVIDIA GPU的Rowhammer攻击专业的技术
  • 配电网故障重构:基于Matlab与Yalmip的二阶锥实现
  • 石蜡加热熔化:COMSOL 多物理场耦合仿真的奇妙之旅