NOIP 模拟 $79\; \rm y$
题解 \(by\;zj\varphi\)
NOIP2013 的原题
最简单的思路就是一个 bfs,可以拿到 \(70pts\)
75pts
#include<bits/stdc++.h>
#define ri signed
#define pd(i) ++i
#define bq(i) --i
#define func(x) std::function<x>
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
#define debug1(x) std::cerr << #x"=" << x << ' '
#define debug2(x) std::cerr << #x"=" << x << std::endl
#define Debug(x) assert(x)
struct nanfeng_stream{
template<typename T>inline nanfeng_stream &operator>>(T &x) {
bool f=false;x=0;char ch=gc();
while(!isdigit(ch)) f|=ch=='-',ch=gc();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
return x=f?-x:x,*this;
}
}cin;
}
using IO::cin;
namespace nanfeng{
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
static const int N=31;
static const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
int n,m,q,ex,ey,sx,sy,tx,ty;
bool vis[N][N][N][N],est[N][N];
struct Que{int x,y,nx,ny,stp;}que[N*N*N*N];
auto bfs=[]() {
int hd=1,tl=0;
que[tl=1].x=ex,que[1].y=ey;
que[1].nx=sx,que[1].ny=sy;
while(hd<=tl) {
int x=que[hd].x,y=que[hd].y;
for (ri i(0);i<4;pd(i)) {
int stx=x+dx[i],sty=y+dy[i],nx=que[hd].nx,ny=que[hd].ny;
if (stx==nx&&sty==ny) nx=x,ny=y;
if (stx<1||stx>n||sty<1||sty>m||!est[stx][sty]||vis[stx][sty][nx][ny]) continue;
++tl;
que[tl].x=stx,que[tl].y=sty,que[tl].nx=nx,que[tl].ny=ny,que[tl].stp=que[hd].stp+1;
vis[stx][sty][nx][ny]=true;
if (nx==tx&&ny==ty) return que[tl].stp;
}
++hd;
}
return -1;
};
inline int main() {
// FI=freopen("y.in","r",stdin);
// FO=freopen("y.out","w",stdout);
cin >> n >> m >> q;
for (ri i(1);i<=n;pd(i))
for (ri j(1);j<=m;pd(j)) cin >> est[i][j];
for (ri z(1);z<=q;pd(z)) {
cin >> ex >> ey >> sx >> sy >> tx >> ty;
if (sx==tx&&sy==ty) printf("0\n");
else {
memset(vis,false,sizeof(vis));
printf("%d\n",bfs());
}
}
return 0;
}
}
int main() {return nanfeng::main();}
常数写小一点,再开个 \(O2\) 洛谷和 loj 就过了。
正解:
对于一个点,它能移动只有当它周围四个方向存在空格子时,所以一个思路就是先将空格子移动到初始格子周围,再向目标点移动,同时维护空格点的位置。
设 \(move_{x,y,t1,t2}\) 表示当前在 \((x,y)\) 的格子,由空格子在它的左/上侧转移到右/下侧需要多少步,这个可以 bfs 预处理出来。
然后在询问时再用一个 bfs 处理出空格子到初始点的四个状态中所需要的步数。
设 \(f_{x,y,t}\) 表示点 \((x,y)\),空格在它的 \(t\) 状态,由初始点转移过来要多少步。
转移就是 \(f_{x,y,t}=\min (f_{xx,yy,tt}+mv_{xx,yy,tt,i}+1)\)
其中 \(t\) 是 \(i\) 对称过去的状态,\((x,y)\) 是 \((xx,yy)\) 周围的点。
最后跑一个最短路,特判一下无解。
Code
#include<bits/stdc++.h>
#define ri signed
#define pd(i) ++i
#define bq(i) --i
#define func(x) std::function<x>
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
#define debug1(x) std::cerr << #x"=" << x << ' '
#define debug2(x) std::cerr << #x"=" << x << std::endl
#define Debug(x) assert(x)
struct nanfeng_stream{
template<typename T>inline nanfeng_stream &operator>>(T &x) {
bool f=false;x=0;char ch=gc();
while(!isdigit(ch)) f|=ch=='-',ch=gc();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
return x=f?-x:x,*this;
}
}cin;
}
using IO::cin;
namespace nanfeng{
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
static const int N=31;
static const int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
int mv[N][N][4][4],dis[N][N][4],n,m,q,ex,ey,sx,sy,tx,ty,cnt;
bool vis[N][N],vs[N][N][4],est[N][N];
struct Que{int x,y,d;}qe[N*N*N*N];
auto bfs=[](int x,int y,int f1,int f2) {
int sx=x+dx[f1],sy=y+dy[f1],tx=x+dx[f2],ty=y+dy[f2];
if ((!est[sx][sy])||(!est[tx][ty])) return;
std::queue<Que> que;
Que tmp={sx,sy,0};
que.push(tmp);
memset(vis,false,sizeof(vis));
vis[x][y]=vis[sx][sy]=true;
while(!que.empty()) {
tmp=que.front(),que.pop();
for (ri i(0);i<4;pd(i)) {
int kx=tmp.x+dx[i],ky=tmp.y+dy[i];
if (kx<1||kx>n||ky<1||ky>m) continue;
if (!vis[kx][ky]&&est[kx][ky]) {
vis[kx][ky]=true;
Que nw={kx,ky,tmp.d+1};
if (kx==tx&&ky==ty) {mv[x][y][f1][f2]=nw.d;return;}
que.push(nw);
}
}
}
};
auto init=[]() {
memset(mv,0x3f,sizeof(mv));
for (ri i(1);i<=n;pd(i))
for (ri j(1);j<=m;pd(j))
if (est[i][j])
for (ri k(0);k<4;pd(k))
for (ri l(0);l<4;pd(l))
if (l==k) mv[i][j][k][l]=0;
else bfs(i,j,k,l);
};
auto solve=[](int x,int y) {
cnt=0;
memset(vis,false,sizeof(vis));
vis[x][y]=vis[sx][sy]=true;
Que tmp={x,y,0};
std::queue<Que> que;
que.push(tmp);
while(!que.empty()) {
tmp=que.front(),que.pop();
for (ri i(0);i<4;pd(i)) {
int kx=tmp.x+dx[i],ky=tmp.y+dy[i];
if (kx<1||kx>n||ky<1||ky>m) continue;
if (est[kx][ky]&&!vis[kx][ky]) {
vis[kx][ky]=true;
que.push({kx,ky,tmp.d+1});
} else if (kx==sx&&ky==sy) qe[++cnt]={kx,ky,(i+2)%4},dis[kx][ky][(i+2)%4]=tmp.d;
}
}
};
auto spfa=[]() {
memset(vs,false,sizeof(vs));
std::queue<Que> que;
for (ri i(1);i<=cnt;pd(i)) que.push(qe[i]),vs[qe[i].x][qe[i].y][qe[i].d]=true;
Que tmp;
while(!que.empty()) {
tmp=que.front(),que.pop();
vs[tmp.x][tmp.y][tmp.d]=false;
for (ri i(0);i<4;pd(i)) {
int kx=tmp.x+dx[i],ky=tmp.y+dy[i],td;
if (kx<1||kx>n||ky<1||ky>m) continue;
if (dis[kx][ky][td=(i+2)%4]>dis[tmp.x][tmp.y][tmp.d]+mv[tmp.x][tmp.y][tmp.d][i]+1) {
dis[kx][ky][td]=dis[tmp.x][tmp.y][tmp.d]+mv[tmp.x][tmp.y][tmp.d][i]+1;
if (!vs[kx][ky][td]) {
vs[kx][ky][td]=true;
que.push({kx,ky,td});
}
}
}
}
};
inline int main() {
FI=freopen("y.in","r",stdin);
FO=freopen("y.out","w",stdout);
cin >> n >> m >> q;
for (ri i(1);i<=n;pd(i))
for (ri j(1);j<=m;pd(j)) cin >> est[i][j];
init();
for (ri z(1);z<=q;pd(z)) {
cin >> ex >> ey >> sx >> sy >> tx >> ty;
if (sx==tx&&sy==ty) printf("0\n");
else {
memset(dis,0x3f,sizeof(dis));
solve(ex,ey);
spfa();
int ans=1061109567;
for (ri i(0);i<4;pd(i)) ans=cmin(ans,dis[tx][ty][i]);
printf("%d\n",ans==1061109567?-1:ans);
}
}
return 0;
}
}
int main() {return nanfeng::main();}
NOIP 模拟 $79\; \rm y$的更多相关文章
- NOIP 模拟 $20\; \rm y$
题解 \(by\;zj\varphi\) 首先发现一共最多只有 \(2^d\) 种道路,那么可以状压,(不要 \(dfs\),会搜索过多无用的状态) 那么设 \(f_{i,j,k}\) 为走 \(i\ ...
- NOIP模拟3
期望得分:30+90+100=220 实际得分:30+0+10=40 T1智障错误:n*m是n行m列,硬是做成了m行n列 T2智障错误:读入三个数写了两个%d T3智障错误:数值相同不代表是同一个数 ...
- 7.22 NOIP模拟7
又是炸掉的一次考试 T1.方程的解 本次考试最容易骗分的一道题,但是由于T2花的时间太多,我竟然连a+b=c都没判..暴力掉了40分. 首先a+b=c,只有一组解. 然后是a=1,b=1,答案是c-1 ...
- NOIP模拟 1
NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. # 用 户 名 ...
- 20190725 NOIP模拟8
今天起来就是虚的一批,然后7.15开始考试,整个前半个小时异常的困,然后一看题,T1一眼就看出了是KMP,但是完了,自己KMP的打法忘的一干二净,然后开始打T2,T2肝了一个tarjan点双就扔上去了 ...
- 20190902+0903合集-NOIP模拟
一直没时间写QwQ 于是补一下. Day 1 晚饭吃的有点恶心…… $1s\,2s\,5s$ 还开 -O2 ?? 有点恐怖. T1 猛的一想: 把外面设成一个点, 向入口连一条权为排队时间的边 从出口 ...
- 2021.5.22 noip模拟1
这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...
- 5.23考试总结(NOIP模拟2)
5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...
- 5.22考试总结(NOIP模拟1)
5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...
随机推荐
- VUE002. 动态使用webpack打包处理后的静态图片路径({ img: require('xxx.png') })
案例摘要 需求是通过v-for循环渲染数组中数据,其中包括本地包的图片文件.话不多说直接上代码: <a-radio-group class="template-radio"& ...
- nacos配置中心模块详解
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star. 配置中心 业务上的配置,功能开关,服务治理上对弱依赖的降级,甚至数据库的密码等,都可能用到动态 ...
- Java日期时间API系列42-----一种高效的中文日期格式化和解析方法
中文日期(2021年09月11日 和 二〇二一年九月十一日 )在生活中经常用到,2021年09月11日很好处理直接使用模板:yyyy年MM月dd日:二〇二一年九月十一日比较不好处理,需要每个数字进行转 ...
- Java入门准备:Java开发环境的安装与卸载
Java的三大版本 JavaSE:标准版 JavaME:嵌入式开发 JavaEE:企业级开发 JDK(Java Development Kit):Java开发者工具包 JRE(Java Runtime ...
- open failed: EACCES (Permission denied)
出现背景:调用系统相册进行图片展示,但是没有成功,是空白的,且检查权限无问题 解决方法
- JAVA语言程序设计课程评价
紧张的又短暂的一个学期结束了,这个学期也许将成为我人生中一个重要的转折点,作为一名半路出家的选手,在初次了解Java语言时我感到非常的迷茫与不知所措.因为之前很多同学都是通过假期时间在家自学,刚转入新 ...
- [Python]爬虫获取知乎某个问题下所有图片并去除水印
获取URL 进入某个知乎问题的主页下,按F12打开开发者工具后查看network面板. network面板可以查看页面向服务器请求的资源.资源的大小.加载资源花费的时间以及哪些资源加载失败等信息.还可 ...
- PHP的OpenSSL加密扩展学习(三):证书操作
关于对称和非对称的加密操作,我们已经学习完两篇文章的内容了,接下来,我们就继续学习关于证书的生成. 生成 CSR 证书签名请求 CSR 是用于生成证书的签名请求,在 CSR 中,我们需要一些 dn 信 ...
- 在PHP中如何为匿名函数指定this?
在之前的文章中,我们已经学习过匿名函数的使用,没有看过的小伙伴可以进入传送门先去了解下闭包匿名函数的用法,传送:还不知道PHP有闭包?那你真OUT了. 关于闭包匿名函数,在JS中有个很典型的问题就是要 ...
- Jmeter系列(35)- 设置JVM内存
场景 单台机器的下JMeter启动较大线程数时可能会出现运行报错的情况,或者在运行一段时间后,JMeter每秒生成的请求数会逐步下降,直到为0,即JMeter运行变得很"卡",这时 ...