这道题赛时的时候想了一个奇怪的做法但是没过,后来经过Stay_hungry的提示就码了这道题。

雷电必定会在一点处分叉,分别电击地上的两个点,我们只需要枚举这个分叉点。那么怎么算出这个点和目标点的距离呢,很容易可以想到用最短路来求解。在仔细算一下复杂度\(O({V}log{E}+n^2)\) (\(V\)为点的个数 \(E\)为边的个数)

这道题其实可以转化为图论题,就是从起点和两个终点分别跑一遍最短路,然后枚举那个闪电分开的点,在将三个\(dis_x\)(\(x\)为当前枚举的点的编号)加起来,取个\(Min\)就可以了。

细节处理都在代码中

  1. //必须要开 long long 不然电阻R加起来会炸
  2. //但是#define int long long 会MLE
  3. //所以就把几个dis数组开long long就好了
  4. #include <bits/stdc++.h>
  5. #define Reg register
  6. using namespace std;
  7. const int N=1e3+10;
  8. inline long long Min(long long a,long long b) { return a<b?a:b; }
  9. inline int read() {
  10. int x=0,f=0; char c=getchar();
  11. while(!isdigit(c)) f|=(c=='-'),c=getchar();
  12. while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
  13. return f?-x:x;
  14. }
  15. struct node {
  16. int u;
  17. long long d;
  18. inline bool operator <(const node &rhs) const {
  19. return d>rhs.d;
  20. }
  21. } ;
  22. struct Edge {
  23. int next,to,w;
  24. } edge[N*N*6];
  25. int n=read(),m=read(),sx=read(),e1=read(),e2=read(),tot;
  26. long long ans=5e18;
  27. int head[N*N],a[N][N];
  28. long long diss[N*N],dis1[N*N],dis2[N*N];
  29. //建边
  30. inline void Addedge(int u,int v,int w) {
  31. edge[++tot]=(Edge){head[u],v,w};
  32. head[u]=tot;
  33. }
  34. //Dijkstra
  35. inline void Dijkstra(int s,long long *dis) {
  36. for(Reg int i=1;i<=n*m;i++)
  37. dis[i]=5e18;
  38. //将起点的初值设置为这个位置的电阻值
  39. if(s%m)
  40. dis[s]=a[s/m+1][s%m];
  41. else
  42. dis[s]=a[s/m][m];
  43. priority_queue<node>que;
  44. que.push((node){s,0});
  45. while(!que.empty()) {
  46. node front=que.top(); que.pop();
  47. int u=front.u;
  48. // if(d==dis[u])
  49. for(Reg int i=head[u];i;i=edge[i].next) {
  50. int v=edge[i].to,w=edge[i].w;
  51. // cout<<u<<' '<<v<<' '<<w<<'\n';
  52. if(dis[u]+w<dis[v]) {
  53. dis[v]=dis[u]+w;
  54. que.push((node){v,dis[v]});
  55. }
  56. }
  57. }
  58. }
  59. signed main() {
  60. //将网格图转化为有向图
  61. for(Reg int i=1;i<=n;i++)
  62. for(Reg int j=1;j<=m;j++) {
  63. a[i][j]=read();
  64. //将每个点的编号设为从左往右数,从上往下数第几个
  65. //连边时连的是它四周的四个点连向它自己,所以边权是为这个点的电阻值
  66. if(j>1)//这是防止向上一个网格连的时候越界,下同
  67. Addedge((i-1)*m+j-1,(i-1)*m+j,a[i][j]);
  68. if(j<m)
  69. Addedge((i-1)*m+j+1,(i-1)*m+j,a[i][j]);
  70. if(i>1)
  71. Addedge((i-2)*m+j,(i-1)*m+j,a[i][j]);
  72. if(i<n)
  73. Addedge(i*m+j,(i-1)*m+j,a[i][j]);
  74. }
  75. Dijkstra(sx,diss)/*,puts("---")*/,Dijkstra(m*(n-1)+e1,dis1)/*,puts("---")*/,Dijkstra(m*(n-1)+e2,dis2);
  76. //跑三遍Dijkstra
  77. //枚举中间点
  78. for(Reg int i=1;i<=n;i++)
  79. for(Reg int j=1;j<=m;j++)
  80. //因为中间点会被计算三次,所以要减去两次
  81. ans=Min(ans,diss[(i-1)*m+j]+dis1[(i-1)*m+j]+dis2[(i-1)*m+j]-2*a[i][j])/*,printf("I=%d,J=%d,Dis=%d,%d,%d\n",i,j,diss[(i-1)*m+j],dis1[(i-1)*m+j],dis2[(i-1)*m+j])*/;
  82. cout<<ans<<'\n';
  83. return 0;
  84. }

Luogu P6833 【[Cnoi2020]雷雨】的更多相关文章

  1. [Cnoi2020]线性生物

    期望入门题.但是我不会做. 考虑设\(E_{x\to{x+1}}\)为\(x\)到\(x+1\)点的期望步数. 则\(ans = \sum_{i = 0}^{n} E_{x\to{x+1}}\) 知\ ...

  2. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

  3. luogu p1268 树的重量——构造,真正考验编程能力

    题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...

  4. [luogu P2170] 选学霸(并查集+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...

  5. [luogu P2647] 最大收益(贪心+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...

  6. Luogu 考前模拟Round. 1

    A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...

  7. luogu P2580 于是他错误的点名开始了

    luogu  P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...

  8. CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)

    CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...

  9. Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)

    Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...

随机推荐

  1. 用 Java 实现的八种常用排序算法

    八种排序算法可以按照如图分类 交换排序 所谓交换,就是序列中任意两个元素进行比较,根据比较结果来交换各自在序列中的位置,以此达到排序的目的. 1. 冒泡排序 冒泡排序是一种简单的交换排序算法,以升序排 ...

  2. 第十六章 IP子网的划分

    一.引入 1.根据IP地址的类别进行IP地址分配的方法表现出越来越多的弊端 2.为了解决分类IP地址划分带来的地址浪费,就需要使用子网划分(Subnetting)的方法 3.VLSM和CIDR可以进一 ...

  3. 构建调试Linux内核网络的环境Menuos系统

    一.Linux内核源码下载 下载网址为:https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz 下载完成后放入home/Menu ...

  4. 【应用服务 App Service】当遇见某些域名在Azure App Service中无法解析的错误,可以通过设置指定DNS解析服务器来解决

    问题情形 当访问部署在Azure App Service中的应用返回 "The remote name could not be resolved: ''xxxxxx.com'" ...

  5. js实现无缝连接轮播图(七)实现左侧按钮的功能

    <!-- 这个animate.js 必须写到 index.js的上面引入 --><script src="js/animate.js"></scrip ...

  6. Dubbo源码本地运行demo遇到的问题

    从github上拉下来的Dubbo源码,运行Dubbo项目的demo工程,报如下错误(Dubbo版本为2.7.6): Exception in thread "main" java ...

  7. Linux下使用select延时

    在LINUX用户态的情况下,如果想要延时的话,可以使用用sleep函数,但是在一些情况下,需要更小单位的延时,ms/us 也是要的.用循环获取到的延时是不精确的. sleep是不准确,这个函数是可以中 ...

  8. 看完这篇良心帖!你的Python入门基础就差不多了

    有段时间没跟各位粉丝分享编程资源福利了,看了下自己的资料夹,就剩下我认为比较好的Python学习资料了.相信这套资料可以对你进阶高级工程师有帮助!全民学Python的话题铺天盖地,中国的Python学 ...

  9. 最新主流 Markdown 编辑器推荐

    Markdown ,2004年由 John Gruberis 设计和开发,是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式,以下将介绍目前比较流行的一 ...

  10. 走在深夜的小码农 Second Day

    HTML5 Second Day writer:late at night codepeasant 学习大纲 表格 表格的主要作用 表格主要用于显示.展示数据,因为它可以让数据显示的非常的规整,可读性 ...