BZOJ2143 飞飞侠 & [校内NOIP2018模拟20181026] 最强大脑
Time Limit: 50 Sec Memory Limit: 259 MB
Description
飞飞国是一个传说中的国度,国家的居民叫做飞飞侠。飞飞国是一个N×M的矩形方阵,每个格子代表一个街区。然而飞飞国是没有交通工具的。飞飞侠完全靠地面的弹射装置来移动。每个街区都装有弹射装置。使用弹射装置是需要支付一定费用的。而且每个弹射装置都有自己的弹射能力。我们设第i行第j列的弹射装置有Aij的费用和Bij的弹
射能力。并规定有相邻边的格子间距离是\(1\)。那么,任何飞飞侠都只需要在(i,j)支付Aij的费用就可以任意选择弹
到距离不超过Bij的位置了。如下图

(从红色街区交费以后可以跳到周围的任意蓝色街区。)现在的问题很简单。有三个飞飞侠,分别叫做X,Y,Z。
现在它们决定聚在一起玩,于是想往其中一人的位置集合。告诉你3个飞飞侠的坐标,求往哪里集合大家需要花的
费用总和最低。
Input
输入的第一行包含两个整数\(N\)和\(M\),分别表示行数和列数。
接下来是2个N×M的自然数矩阵,为\(B_{i,j}\)和\(A_{i,j}\)
最后一行六个数,分别代表X,Y,Z所在地的行号和列号。
\(1\leq N,M\leq 150\);\(0\leq B_{i,j}\leq 10^9\);\(0\leq A_{i,j}\leq1000\)
Output
第一行输出一个字符X、Y或者Z。表示最优集合地点。
第二行输出一个整数,表示最小费用。如果无法集合,只输出一行NO
Sample Input
4 4
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2
Sample Output
Z
15
Solution
嗯这道题的算法还是很有意思的,有时间还要再好好品味一下,真的是很新奇。
一眼最短路啊,但是如果我们直接跑Dijkstra的话(什么,这个世道你还敢用SPFA,更何况这还是网格图),转移数量太多了,肯定会T掉。
所以我们考虑一下转化,在一个点投射,相当于给了他一个\(B[i][j]\)的能量,然后每走一个消耗一个点数的能量。
那么我们设\(dist[i][j][k]\)表示走到\((i,j)\)这个点,还剩\(k\)点的能量的情况。那么转移就是这样的:
&dp[i][j][k]\rightarrow dp[x][y][k-1]\ \ |\ \ k>0,\text{$(x,y)$是与$(i,j)$香菱的点}\\
&dp[i][j][0]+a[i][j]\rightarrow dp[i][j][b[i][j]]\\
\end{align*}
\]
这样然后再加上Dijsktra的堆的复杂度就是\(O(n^3\log (n^3))\)的。比较卡常,在学校OJ上过不去,BZOJ上好像能过。
我们考虑优化。后面的学长们讨论了各种各样的优化,比如什么线段树优化建边,线段树进行转移,并查集优化最短路什么的。
但是这些我都不太会,所以只能自己YY出了一个实测效果很好的优化。显然Dijkstra里面每一次进行操作的点的\(dist\)值是单调不减的,所以如果遇到这样的情况我们可以直接跳过,不去转移:同一个点,如果已经操作过比现在这个状态能量要多的点,那么显然现在这个状态没有那个优,就可以不去转移了。我们只需要每次都转移那些能量大于曾经转移过的同一个点的能量值最大值的状态。这样的话,我们可以优化掉很多没有用的状态,实测效果不错,在BZOJ上排到了第二页,不过还是比不上那些神一样的并查集优化最短路。
但是遗憾的是,好像这样的复杂度还是没有变的,大家也许可以叉一叉。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define REP(i,a,n) for(register int i=(a);i<=(n);++i)
#define PER(i,a,n) for(register int i=(a);i>=(n);--i)
#define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
namespace io{
const int SIZE=(1<<21)+1;char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];int f,qr;
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
inline void putc(char x){*oS++=x;if(oS==oT)flush();}
template<class I>inline void read(I &x){for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;}
template<class I>inline void write(I x){if(!x)putc('0');if(x<0)putc('-'),x=-x;while(x)qu[++qr]=x%10+'0',x/=10;while(qr)putc(qu[qr--]);}
inline void print(const char *s){while(*s!='\0')putc(*s++);}
inline void scan(char *s){for(c=gc();c<=' ';c=gc());for(;c>' ';c=gc())*(s++)=c;*s='\0';}
struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}//orz laofudasuan
using io::read;using io::putc;using io::write;using io::print;
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline bool SMAX(A&x,const B&y){return x<y?x=y,1:0;}
template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;}
const int N=150+3,INF=0x3f3f3f3f,fx[]={0,0,1,0,-1},fy[]={0,1,0,-1,0};
int n,m,b[N][N],a[N][N],dist[N][N][N<<1],vis[N][N],flag1,flag2,X1,Y1,X2,Y2,X3,Y3,ans=INF,get[4][4];char ans2;//错误笔记:get[4][4]开成了get[3][3]
struct Node{int x,y,en,dist;inline bool operator<(const Node&a)const{return dist>a.dist;}};priority_queue<Node>q;
inline void Dijkstra(Node S,Node T1,Node T2,int &flag1,int &flag2){
memset(dist,0x3f,sizeof(dist));memset(vis,-1,sizeof(vis));while(!q.empty())q.pop();
dist[S.x][S.y][b[S.x][S.y]]=a[S.x][S.y];q.push(Node{S.x,S.y,b[S.x][S.y],a[S.x][S.y]});flag1=flag2=0;
while(!q.empty()){
Node p=q.top();q.pop();if(vis[p.x][p.y]>=p.en)continue;int flag=(vis[p.x][p.y]==-1);SMAX(vis[p.x][p.y],p.en);
if(p.x==T1.x&&p.y==T1.y&&!flag1)flag1=p.dist;if(p.x==T2.x&&p.y==T2.y&&!flag2)flag2=p.dist;if(flag1&&flag2)return;
for(register int i=0;i<=4;++i){
Node f=Node{p.x+fx[i],p.y+fy[i],p.en-1,p.dist};if(f.x<1||f.x>n||f.y<1||f.y>m)continue;
if(vis[f.x][f.y]<=f.en&&dist[f.x][f.y][f.en]>p.dist){
dist[f.x][f.y][f.en]=dist[p.x][p.y][p.en];
q.push(f);
}
}
if(flag){Node f=Node{p.x,p.y,b[p.x][p.y],p.dist+a[p.x][p.y]};
if(vis[f.x][f.y]<=f.en&&dist[f.x][f.y][f.en]>p.dist+a[p.x][p.y]){
dist[f.x][f.y][f.en]=p.dist+a[p.x][p.y];
q.push(f);
}}
}if(!flag1)flag1=INF;if(!flag2)flag2=INF;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("zhber.in","r",stdin);freopen("zhber.out","w",stdout);
#endif
read(n),read(m);
for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)read(b[i][j]),SMIN(b[i][j],max(max(i-1+j-1,n-i+j-1),max(i-1+m-j,n-i+m-j)));
for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)read(a[i][j]);
read(X1),read(Y1),read(X2),read(Y2),read(X3),read(Y3);
Dijkstra(Node{X1,Y1},Node{X2,Y2},Node{X3,Y3},get[1][2],get[1][3]);
Dijkstra(Node{X2,Y2},Node{X1,Y1},Node{X3,Y3},get[2][1],get[2][3]);
Dijkstra(Node{X3,Y3},Node{X1,Y1},Node{X2,Y2},get[3][1],get[3][2]);
if(SMIN(ans,get[2][1]+get[3][1]))ans2='X';
if(SMIN(ans,get[1][2]+get[3][2]))ans2='Y';
if(SMIN(ans,get[1][3]+get[2][3]))ans2='Z';
if(ans2<'X')print("NO\n");else putc(ans2),putc('\n'),write(ans),putc('\n');
}
BZOJ2143 飞飞侠 & [校内NOIP2018模拟20181026] 最强大脑的更多相关文章
- BZOJ2143: 飞飞侠
2143: 飞飞侠 题意: 给出两个 n ∗ m 的矩阵 A,B,以及 3 个人的坐标 在 (i, j) 支付 Ai,j 的费用可以弹射到曼哈顿距离不超过 Bi,j 的位置 问三个人汇合所需要的最小总 ...
- 2018.11.05 bzoj2143: 飞飞侠(最短路)
传送门 最短路好题. 考虑对每个二维坐标建立一个高度属性. 这样每次如果在点(i,j,0)(i,j,0)(i,j,0)只能选择花费bi,jb_{i,j}bi,j跳向(i,j,ai,j)(i,j,a_ ...
- bzoj千题计划225:bzoj2143: 飞飞侠
http://www.lydsy.com/JudgeOnline/problem.php?id=2143 分层图最短路 把能够弹跳的曼哈顿距离看做能量 dp[i][j][k]表示在(i,j)位置,还有 ...
- [BZOJ2143]飞飞侠 并查集优化最短路
链接 题解 首先很容易想到对每个点暴力跑Dijkstra,但是这样边数是 \(N^4\) 的,考虑优化 发现每次松弛的时候,都要把整个地图扫一遍,每个节点都要重复扫很多次,如果我们在一个点不会再被更新 ...
- BZOJ3508 开灯 & [校内NOIP2018模拟20181027] 密码锁
Time Limit: 10 Sec Memory Limit: 128 MB Description xx作为信息学界的大神,拥有众多的粉丝.为了感谢众粉丝的爱戴,xx决定举办一场晚会.为了气派,x ...
- 刷题总结——飞飞侠(bzoj2143 最短路)
题目: Description 飞飞国是一个传说中的国度,国家的居民叫做飞飞侠.飞飞国是一个N×M的矩形方阵,每个格子代表一个街区.然而飞飞国是没有交通工具的.飞飞侠完全靠地面的弹射装置来移动.每个街 ...
- 【BZOJ 2143】 飞飞侠
Description 飞飞国是一个传说中的国度,国家的居民叫做飞飞侠.飞飞国是一个N×M的矩形方阵,每个格子代表一个街区.然而飞飞国是没有交通工具的.飞飞侠完全靠地面的弹射装置来移动.每个街区都装有 ...
- BZOJ 2143 飞飞侠(分层最短路)
飞飞国是一个N×M的矩形方阵,每个格子代表一个街区.然而飞飞国是没有交通工具的.飞飞侠完全靠地面的弹射装置来移动.每个街区都装有弹射装置.使用弹射装置是需要支付一定费用的.而且每个弹射装置都有自己的弹 ...
- [NOIP2018模拟赛10.16]手残报告
[NOIP2018模拟赛10.16]手残报告 闲扯 炉石乱斗模式美滋滋啊,又颓到好晚... 上来T2先敲了树剖,看T1发现是个思博DP,然后没过大样例,写个暴力发现还是没过大样例!?才发现理解错题意了 ...
随机推荐
- python全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)
昨日内容回顾 线程 什么是线程? 线程是cpu调度的最小单位 进程是资源分配的最小单位 进程和线程是什么关系? 线程是在进程中的一个执行单位 多进程 本质上开启的这个进程里就有一个线程 多线程 单纯的 ...
- MySQL server has gone away 问题解决方法
问题描述: SQLyog在执行大的sql文件时候,报错,报错日志显示2006 - MySQL server has gone away 解决办法: 在php.ini配置文件的[mysqld]节点下添加 ...
- pom里引入lib下的包后编译报 package com.sun.crypto.provider does not exist问题解决
最近正在迭代开发的一个项目编译安装时出现报“package com.sun.crypto.provider does not exist”的错误,由于本人能力水平有限,也是第一次遇到该问题,来来回回折 ...
- 133、TensorFlow加载模型(二)
# 选择哪个变量来保存和恢复 # 如果你没有传递任何的参数到tf.train.Saver() # 这个saver会处理计算图中所有的变量 # 每一个变量都被保存,保存的名字就是当初创建他们时候的名字 ...
- 关闭myeclipse中烦人的鼠标划过,自动提示功能
eclipse越来越智能,身为码农的我却越来越伤心.虽然你很智能,但请你提供一些有用的信息给我,不要乱七八槽的,不问青红皂白就塞一大堆提示给我,对不起,哥不需要这些!!! 都知道,使用myeclips ...
- delphi 牛逼 了 app (已在软件界掀起波澜)10分钟10行代码做出让人惊叹的程序
(已在软件界掀起波澜)10分钟10行代码做出让人惊叹的程序 http://v.qq.com/x/page/m0328h73bs7.html?ptag=bbs_csdn_net
- Vue访问子组件实例或子元素
1 尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件(例如,调用子组件的方法).为了达到这个目的,你可以通过 ref 特性为这个子组件赋予一个 ID 引用 ...
- SQL标量函数
调用 MS SQL 标量值函数,应该在函数前面加上 "dbo.",否则会报 “不是可以识别的 内置函数名称”错误.例如 DECLARE @WhichDB TINYINT; ...
- PHP学习 fwrite:Warning: fwrite(): supplied argument is not avalid stream resource in
使用fwrite报错:Warning: fwrite(): supplied argument is not avalid stream resource in 解决方法:文件权限的问题,文件需要77 ...
- emacs配置&博客界面源代码
emacs配置 如果想要考场简单配置也可以去下面看,需要别的考场配置可以自己在下面比较全的里面找 考试备忘录(有新的就会更的...) By Junlier (global-set-key [f9] ' ...