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

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

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

细节处理都在代码中

//必须要开 long long 不然电阻R加起来会炸
//但是#define int long long 会MLE
//所以就把几个dis数组开long long就好了 #include <bits/stdc++.h>
#define Reg register
using namespace std;
const int N=1e3+10;
inline long long Min(long long a,long long b) { return a<b?a:b; }
inline int read() {
int x=0,f=0; char c=getchar();
while(!isdigit(c)) f|=(c=='-'),c=getchar();
while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f?-x:x;
}
struct node {
int u;
long long d;
inline bool operator <(const node &rhs) const {
return d>rhs.d;
}
} ;
struct Edge {
int next,to,w;
} edge[N*N*6];
int n=read(),m=read(),sx=read(),e1=read(),e2=read(),tot;
long long ans=5e18;
int head[N*N],a[N][N];
long long diss[N*N],dis1[N*N],dis2[N*N];
//建边
inline void Addedge(int u,int v,int w) {
edge[++tot]=(Edge){head[u],v,w};
head[u]=tot;
}
//Dijkstra
inline void Dijkstra(int s,long long *dis) {
for(Reg int i=1;i<=n*m;i++)
dis[i]=5e18;
//将起点的初值设置为这个位置的电阻值
if(s%m)
dis[s]=a[s/m+1][s%m];
else
dis[s]=a[s/m][m];
priority_queue<node>que;
que.push((node){s,0});
while(!que.empty()) {
node front=que.top(); que.pop();
int u=front.u;
// if(d==dis[u])
for(Reg int i=head[u];i;i=edge[i].next) {
int v=edge[i].to,w=edge[i].w;
// cout<<u<<' '<<v<<' '<<w<<'\n';
if(dis[u]+w<dis[v]) {
dis[v]=dis[u]+w;
que.push((node){v,dis[v]});
}
}
}
}
signed main() {
//将网格图转化为有向图
for(Reg int i=1;i<=n;i++)
for(Reg int j=1;j<=m;j++) {
a[i][j]=read();
//将每个点的编号设为从左往右数,从上往下数第几个
//连边时连的是它四周的四个点连向它自己,所以边权是为这个点的电阻值
if(j>1)//这是防止向上一个网格连的时候越界,下同
Addedge((i-1)*m+j-1,(i-1)*m+j,a[i][j]);
if(j<m)
Addedge((i-1)*m+j+1,(i-1)*m+j,a[i][j]);
if(i>1)
Addedge((i-2)*m+j,(i-1)*m+j,a[i][j]);
if(i<n)
Addedge(i*m+j,(i-1)*m+j,a[i][j]);
}
Dijkstra(sx,diss)/*,puts("---")*/,Dijkstra(m*(n-1)+e1,dis1)/*,puts("---")*/,Dijkstra(m*(n-1)+e2,dis2);
//跑三遍Dijkstra
//枚举中间点
for(Reg int i=1;i<=n;i++)
for(Reg int j=1;j<=m;j++)
//因为中间点会被计算三次,所以要减去两次
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])*/;
cout<<ans<<'\n';
return 0;
}

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. 多测师讲解自动化测试 _RFalert弹框._高级讲师肖sir

    alert弹框定位 Open Browser file:///D:\\bao\\baoan\\alert弹框.html gc sleep 2 Handle Alert accept #点击确定 Han ...

  2. 【C语言C++编程入门】程序的可读性和函数的调用!

    一个简单程序的结构 你已经看过一个具体的例子,下面可以了解一些 C程序的基本规则了. 程序由一个或多个函数组成,其中一定有一个名为 main()的函数.函数的描述由函数头和函数体组成.函数头包括预处理 ...

  3. 【原创】xenomai3.1+linux构建linux实时操作系统-基于X86_64和arm

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 一.概要 二.环境准备 1.1 安装内核编译工 ...

  4. php生成器 yield 转

    一.yield介绍  文档介绍说道:生成器函数的核心是yield关键字.它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并终止函数的执行,而yield会返回一个值给 ...

  5. from lxml import etree报错

    使用的是python3.7的环境,解析数据要用xpath,系统是mac pip install lxml一分钟后...下载成功 开始写代码, from lxml import etree挂了-,lxm ...

  6. c# 误区系列(二)

    前言 继续整理误区系列,可能会对刚入门的新手有些帮助,然后希望有错误的地方可以指出. 正文 关于泛型方法的确定 class Person<T> { public void add(T a) ...

  7. openresty下安装luarocks

    wget https://luarocks.org/releases/luarocks-2.4.1.tar.gz tar -xzvf luarocks-2.4.1.tar.gz cd luarocks ...

  8. Python 为什么入门容易 精通难

    Python都说是最容易学习的编程语言,但是为什么还是有很多的小白在学习的过程中学的云里雾里,一天到晚都是报错,异常,这也怪不得会有那么多人说,学Python是从入门到入土! 其实一门编程语言不像语文 ...

  9. js逻辑程序

    JavaScript 是 Web 的编程语言. 所有现代的 HTML 页面都使用 JavaScript. JavaScript 非常容易学. 本教程将教你学习从初级到高级 JavaScript 知识. ...

  10. Eureka+Hystrix(断路器、熔断器)

    红圈是断路器的三种状态: 关闭:1.当consumer访问provider时,在网络超时访问内,访问成功: 2.有时互相调用会出现网络涌动,(比如北京访问广东的服务器要经过很多次路由才能达到并相应), ...