【JZOJ4861】【NOIP2016提高A组集训第7场11.4】推冰块
题目描述
Dpstr最近迷上了推冰块。冰地是一个n行m列的网格区域,第i行第j列的格子记为(i,j),也就是左上角为(1,1),右下角为(n,m)。每个格子可能是冰面、障碍物、减速带三者之一。其中,冰地外围(即第0行、第n+1行、第0列、第m+1列)的所有格子均有障碍物。除此之外,冰地内共有k个障碍物和减速带,其余格子为冰面。
初始时,有一个冰块位于(1,1)处。Dpstr每次可以选择上、下、左、右四个方向之一推动该冰块,推动后该冰块将一直沿此方向移动,直到冰块所在的格子为减速带,或冰块沿运动方向的下一个格子为障碍物时,冰块将停止运动。一旦冰块停在减速带上,该减速带即消失。
Dpstr希望通过尽量少的推动次数使得冰块停在(n,m)处。请计算Dpstr至少要推多少次冰块。
数据范围
对于30%的数据,2≤n≤5,2≤m≤5,0≤k≤5;
对于50%的数据,2≤n≤1,000,2≤m≤1,000,0≤k≤1,000;
对于70%的数据,2≤n≤50,000,2≤m≤50,000,0≤k≤50,000;
对于100%的数据,2≤n≤1,000,000,000,2≤m≤1,000,000,000,0≤k≤50,000,1≤xi≤n,1≤yi≤m,0≤ti≤1。
解法
显然每个格子最多只会走一次。
所以可以使用BFS。
运用二分解决滑行问题。
代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="ice.in";
const char* fout="ice.out";
const ll inf=0x7fffffff;
const ll maxn=50007,maxt=1000007;
const ll fx[4][2]={{0,-1},{-1,0},{1,0},{0,1}};
ll n,m,n1,i,j,k,l,ans=inf;
struct node{
ll x,y,z;
void operator =(const node &j){
x=j.x;
y=j.y;
z=j.z;
}
}f[maxn],g[maxn];
ll b[maxt][2],head,tail;
ll h[maxt],dis[maxt];
ll hash(ll x){
ll t=x%maxt;
while (h[t] && h[t]!=x) t=(t+1)%maxt;
return t;
}
ll pos(ll x,ll y){
return (x-1)*m+y;
}
void add(ll x,ll y,ll z){
ll k=pos(x,y),i,j;
i=hash(k);
if (!h[i]) {
h[i]=k;
dis[i]=z;
b[++tail][0]=x;
b[tail][1]=y;
}
}
void bfs(ll x,ll y){
ll xx[4],yy[4],i,j,k,dist,now,l,r,mid,o;
bool bz[4];
add(x,y,0);
while (head++<tail){
j=b[head][0];
k=b[head][1];
now=hash(pos(j,k));
memset(bz,0,sizeof(bz));
l=1;
r=n1;
while (l<r){
mid=(l+r+1)/2;
if (f[mid].x<j || f[mid].x==j && f[mid].y<k) l=mid;
else r=mid-1;
}
for (o=l;o<=l+2;o++){
if (o>n1) break;
if (f[o].x==j && f[o].y<k) {
xx[0]=f[o].x;
yy[0]=f[o].y+(f[o].z==0);
bz[0]=true;
}
if (f[o].x==j && f[o].y>k){
xx[1]=f[o].x;
yy[1]=f[o].y-(f[o].z==0);
bz[1]=true;
break;
}
}
if (!bz[0]) xx[0]=j,yy[0]=1;
if (!bz[1]) xx[1]=j,yy[1]=m;
l=1;
r=n1;
while (l<r){
mid=(l+r+1)/2;
if (g[mid].y<k || g[mid].y==k && g[mid].x<j) l=mid;
else r=mid-1;
}
for (o=l;o<=l+2;o++){
if (o>n1) break;
if (g[o].y==k && g[o].x<j) {
xx[2]=g[o].x+(g[o].z==0);
yy[2]=g[o].y;
bz[2]=true;
}
if (g[o].y==k && g[o].x>j){
xx[3]=g[o].x-(g[o].z==0);
yy[3]=g[o].y;
bz[3]=true;
break;
}
}
if (!bz[2]) xx[2]=1,yy[2]=k;
if (!bz[3]) xx[3]=n,yy[3]=k;
for (i=0;i<4;i++){
add(xx[i],yy[i],dis[now]+1);
if (xx[i]==n && m==yy[i]) ans=min(ans,dis[now]+1);
}
}
}
bool cmp(node a,node b){
return a.x<b.x || a.x==b.x && a.y<b.y;
}
bool cmp1(node a,node b){
return a.y<b.y || a.y==b.y && a.x<b.x;
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d%d",&n,&m,&n1);
for (i=1;i<=n1;i++) scanf("%d%d%d",&f[i].x,&f[i].y,&f[i].z),g[i]=f[i];
sort(f+1,f+n1+1,cmp);
sort(g+1,g+n1+1,cmp1);
bfs(1,1);
printf("%lld",ans);
return 0;
}
启发
对于搜索题,从最简单的搜索入手。
初始搜索最好打bfs,因为最容易优化,而且最短路最快找到。
然后根据客观的时间耗费,优化对应的地方。
【JZOJ4861】【NOIP2016提高A组集训第7场11.4】推冰块的更多相关文章
- JZOJ 【NOIP2016提高A组集训第16场11.15】兔子
JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...
- JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线
JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...
- 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集
题目描述 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 数据范围 40%的数据满足: ...
- 【NOIP2016提高A组集训第14场11.12】随机游走
题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...
- 【NOIP2016提高A组集训第13场11.11】最大匹配
题目 mhy12345学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边. 图的"匹配"是指这个图的一个边集,里面的边两两不存在公 ...
- 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP
好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...
- 【JZOJ4901】【NOIP2016提高A组集训第18场11.17】矩阵
题目描述 他是一名普通的农电工,他以一颗无私奉献的爱岗敬业之心,刻苦钻研业务,以娴熟的技术.热情周到的服务赢得了广大客户的尊敬和赞美.他就是老百姓称为"李电"的李春来. 众所周知, ...
- 【JZOJ4898】【NOIP2016提高A组集训第17场11.16】人生的价值
题目描述 NiroBC终于找到了人生的意义,可是她已经老了,在新世界,没有人认识她,她孤独地在病榻上回顾着自己平凡的一生,老泪纵横.NiroBC多么渴望再多活一会儿啊! 突然一个戴着黑色方框眼镜,方脸 ...
随机推荐
- 《DSP using MATLAB》Problem 7.34
代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...
- MySQL数据库 数据库的引擎,模式,数据类型(更新中...)
数据库的引擎:驱动数据的方式-数据库优化 前提:引擎是建表的时候规定的,提供给表使用的,不是数据库 mysql> show engines #展示所有引擎 #几种比较常见的引擎 # innodb ...
- Effective Modern C++ 条款3:理解decltype
说起decltype,这是个古灵精怪的东西.对于给定的名字或表达式,decltype能告诉你该名字或表达式的型别.一般来说,它告诉你的结果和你预测的是一样的.不过,偶尔它也会给出某个结果,让你抓耳挠腮 ...
- Redis源码解析:14Redis服务器与客户端间的交互
Redis服务器是典型的一对多服务器程序,通过使用由IO多路复用技术实现的文件事件处理器,Redis服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信. Redis客户端与服务器之 ...
- 洛谷P4022 熟悉的文章
题意:给定一个串集合s,每次给定一个串t,询问一个最大的L,使得存在一种划分能把t划分成若干个子串, 其中好的子串总长不小于0.9|t|.好的子串定义为长度不小于L且是s中某一个串的子串. 解:发现这 ...
- centos7.6 安装jdk1.8
1. 下载 jdk-8u211-linux-x64.tar.gz文件. 2. 创建/opt/soft目录,# cd /opt, # mkdir soft, #tar -zxvf jdk-8u211- ...
- c++设计模式:访问者模式(visitor模式)
1.c语言中回调基本都过函数指针来完成.c++中主要通过接口的方式完成回调.而visitor就是实现接口回调的一种方式. 1.首先定义个一个接口visitor类, class classVisitor ...
- linux学习 网络系统&文件查找
被用来配置和操作网络系统的命令数目非常巨大,这里仅仅介绍一些经常会使用的 这一章会介绍ssh远程登录程序哦 ping 命令(掠过) traceroute 会显示主机到指定的主机要经过的跳数的网络流量列 ...
- phpBOM头(字符)出现的原因以及解决方法_PHP程序员博客|高蒙个人博客
今天在项目中发现,客户端在使用ajax得到返回值时,无法匹配字符串.总是报错,打开页面接口发现,页面的头部出现了的字符(BOM头),找到问题了,那么直接用代码清除掉即可. php隐形字符 // 如 ...
- spring源码学习之默认标签的解析(一)
继续spring源码的学习之路,现在越来越觉得这个真的很枯燥的,而且我觉得要是自己来看源码,真的看不下去,不是没有耐心,而是真的没有头绪,我觉得结合着书来看,还是很有必要的,最起码大致的流程是能够捋清 ...