Luogu P6833 【[Cnoi2020]雷雨】
这道题赛时的时候想了一个奇怪的做法但是没过,后来经过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]雷雨】的更多相关文章
- [Cnoi2020]线性生物
期望入门题.但是我不会做. 考虑设\(E_{x\to{x+1}}\)为\(x\)到\(x+1\)点的期望步数. 则\(ans = \sum_{i = 0}^{n} E_{x\to{x+1}}\) 知\ ...
- Luogu 魔法学院杯-第二弹(萌新的第一法blog)
虽然有点久远 还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题 沉迷游戏,伤感情 #include <queue> ...
- luogu p1268 树的重量——构造,真正考验编程能力
题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...
- [luogu P2170] 选学霸(并查集+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...
- [luogu P2647] 最大收益(贪心+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...
- Luogu 考前模拟Round. 1
A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...
- luogu P2580 于是他错误的点名开始了
luogu P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...
- CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)
CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...
- Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)
Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...
随机推荐
- 多测师讲解自动化测试 _RFalert弹框._高级讲师肖sir
alert弹框定位 Open Browser file:///D:\\bao\\baoan\\alert弹框.html gc sleep 2 Handle Alert accept #点击确定 Han ...
- 【C语言C++编程入门】程序的可读性和函数的调用!
一个简单程序的结构 你已经看过一个具体的例子,下面可以了解一些 C程序的基本规则了. 程序由一个或多个函数组成,其中一定有一个名为 main()的函数.函数的描述由函数头和函数体组成.函数头包括预处理 ...
- 【原创】xenomai3.1+linux构建linux实时操作系统-基于X86_64和arm
版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 一.概要 二.环境准备 1.1 安装内核编译工 ...
- php生成器 yield 转
一.yield介绍 文档介绍说道:生成器函数的核心是yield关键字.它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并终止函数的执行,而yield会返回一个值给 ...
- from lxml import etree报错
使用的是python3.7的环境,解析数据要用xpath,系统是mac pip install lxml一分钟后...下载成功 开始写代码, from lxml import etree挂了-,lxm ...
- c# 误区系列(二)
前言 继续整理误区系列,可能会对刚入门的新手有些帮助,然后希望有错误的地方可以指出. 正文 关于泛型方法的确定 class Person<T> { public void add(T a) ...
- openresty下安装luarocks
wget https://luarocks.org/releases/luarocks-2.4.1.tar.gz tar -xzvf luarocks-2.4.1.tar.gz cd luarocks ...
- Python 为什么入门容易 精通难
Python都说是最容易学习的编程语言,但是为什么还是有很多的小白在学习的过程中学的云里雾里,一天到晚都是报错,异常,这也怪不得会有那么多人说,学Python是从入门到入土! 其实一门编程语言不像语文 ...
- js逻辑程序
JavaScript 是 Web 的编程语言. 所有现代的 HTML 页面都使用 JavaScript. JavaScript 非常容易学. 本教程将教你学习从初级到高级 JavaScript 知识. ...
- Eureka+Hystrix(断路器、熔断器)
红圈是断路器的三种状态: 关闭:1.当consumer访问provider时,在网络超时访问内,访问成功: 2.有时互相调用会出现网络涌动,(比如北京访问广东的服务器要经过很多次路由才能达到并相应), ...