洛谷 1979 华容道——最短路+dp
题目:https://www.luogu.org/problemnew/show/P1979
感到无从下手。但不妨用dp的角度来看。因为空格只有在指定棋子的旁边才有用,所以状态记成制定棋子的位置与空格在自己的哪侧。
转移有两种:与空格交换位置 或 让空格换一个方向。为了第二个转移,需要预处理,bfs出指定棋子在 (x,y) 时从它的哪边走到哪边的最短路。
dp的转移可以套到最短路里做。一开始需要让空格来到指定棋子的四个方向(bfs)。然后多源最短路或者做4遍最短路。
别忘了优先队列自然的就是从大到小排列的!!!
自己的写法需要特判走0步的情况。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<queue>
- using namespace std;
- const int N=,K=,M=N*N,INF=0x3f3f3f3f-;
- int n,m,Q,f[N][N][K][K],dis[N][N],dp[N][N][K];
- int he,tl,xx[K]={-,,,},yy[K]={,-,,};
- int ex,ey,sx,sy,Tx,Ty,ans,tmp;
- bool b[N][N],vis[N][N][K];
- struct Node{
- int x,y,p,dis;
- Node(int x=,int y=,int a=,int d=):x(x),y(y),p(a),dis(d) {}
- bool operator< (const Node &b) const
- {return dis>b.dis;}//>!!!
- }q[M];
- priority_queue<Node> qu;
- void bfs(int x1,int y1,int x2,int y2)
- {
- he=tl=; int tx,ty;
- q[++tl]=Node(x1,y1,,);
- memset(dis,0x3f,sizeof dis);
- dis[x1][y1]=;
- while(he<tl)
- {
- Node k=q[++he];
- for(int i=;i<=;i++)
- {
- tx=k.x+xx[i]; ty=k.y+yy[i];
- if(!b[tx][ty])continue;
- if(dis[tx][ty]>INF)
- {
- dis[tx][ty]=dis[k.x][k.y]+;
- q[++tl]=Node(tx,ty,,);
- if(tx==x2&&ty==y2)return;
- }
- }
- }
- }
- void init()
- {
- memset(f,0x3f,sizeof f);
- for(int i=;i<=n;i++)
- for(int j=;j<=m;j++) if(b[i][j])
- for(int p0=;p0<=;p0++)
- for(int p1=p0+,x1,y1,x2,y2;p1<=;p1++)
- {
- x1=i+xx[p0]; y1=j+yy[p0];
- x2=i+xx[p1]; y2=j+yy[p1];
- if(!b[x1][y1]||!b[x2][y2]) continue;
- b[i][j]=;
- bfs(x1,y1,x2,y2);
- f[i][j][p0][p1]=f[i][j][p1][p0]
- =dis[x2][y2];
- b[i][j]=;
- }
- }
- void solve(int yp)
- {
- while(qu.size())qu.pop();
- qu.push(Node(sx,sy,yp,));
- memset(dp,0x3f,sizeof dp); dp[sx][sy][yp]=;//
- memset(vis,,sizeof vis);
- while(qu.size())
- {
- Node k=qu.top(); qu.pop();
- if(vis[k.x][k.y][k.p])continue;
- vis[k.x][k.y][k.p]=;
- if(k.x==Tx&&k.y==Ty)return;
- int tp=-k.p,tx=k.x+xx[k.p],ty=k.y+yy[k.p];
- if(dp[tx][ty][tp]>dp[k.x][k.y][k.p]+)
- {
- dp[tx][ty][tp]=dp[k.x][k.y][k.p]+;
- qu.push(Node(tx,ty,tp,dp[tx][ty][tp]));
- }
- tx=k.x; ty=k.y; tp=k.p;
- for(int i=;i<=;i++)
- {
- if(i==tp)continue;
- if(f[tx][ty][tp][i]<INF&&
- dp[tx][ty][i]>dp[tx][ty][tp]+f[tx][ty][tp][i])
- {
- dp[tx][ty][i]=dp[tx][ty][tp]+f[tx][ty][tp][i];
- qu.push(Node(tx,ty,i,dp[tx][ty][i]));
- }
- }
- }
- }
- int main()
- {
- scanf("%d%d%d",&n,&m,&Q);
- for(int i=;i<=n;i++)
- for(int j=,d;j<=m;j++)
- scanf("%d",&d),b[i][j]=d;
- init();
- he=tl=;
- while(Q--)
- {
- scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&Tx,&Ty);
- if(sx==Tx&&sy==Ty)
- {
- printf("0\n"); continue;
- }
- ans=INF+;
- for(int i=,tx,ty;i<=;i++)
- {
- tx=sx+xx[i]; ty=sy+yy[i];
- if(!b[tx][ty])continue;
- b[sx][sy]=;
- bfs(ex,ey,tx,ty);
- b[sx][sy]=;
- tmp=dis[tx][ty];
- if(tmp>INF)continue;
- solve(i);
- ans=min(ans,tmp+min(min(dp[Tx][Ty][],dp[Tx][Ty][]),
- min(dp[Tx][Ty][],dp[Tx][Ty][])));
- }
- printf("%d\n",ans>INF?-:ans);
- }
- return ;
- }
洛谷 1979 华容道——最短路+dp的更多相关文章
- 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
- 洛谷 P1979 华容道 解题报告
P1979 华容道 题目描述 小\(B\)最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时 ...
- 洛谷2344 奶牛抗议(DP+BIT+离散化)
洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...
- Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...
- 洛谷P1541 乌龟棋(四维DP)
To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...
- 【洛谷】P1052 过河【DP+路径压缩】
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...
- 【题解】洛谷P1052 [NOIP2005TG] 过河(DP+离散化)
题目来源:洛谷P1052 思路 一开始觉得是贪心 但是仔细一想不对 是DP 再仔细一看数据不对 有点大 如果直接存下的话 显然会炸 那么就需要考虑离散化 因为一步最大跳10格 那么我们考虑从1到10都 ...
- 洛谷1736(二维dp+预处理)
洛谷1387的进阶版,但很像. 1387要求是“全为1的正方形”,取dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))吧?这个有“只有对 ...
- 【洛谷4933】大师(DP)
题目: 洛谷4933 分析: (自己瞎yy的DP方程竟然1A了,写篇博客庆祝一下) (以及特斯拉电塔是向Red Alert致敬吗233) 这里只讨论公差不小于\(0\)的情况,小于\(0\)的情况进行 ...
随机推荐
- git分支处理
查看分支:git branch 创建分支:git branch <name> 切换分支:git checkout <name> 创建+切换分支:git checkout -b ...
- a标签javascript传参不正确的解决办法!
代码部分: <a href="javascript:void(0);" onClick="findList(${goodsClassify.id})"&g ...
- 【Python基础】之for循环、数组字典
一. for循环实例 1.循环字符串 Python Shell: for i in "hello": print(i) h e l l o 2.循环数组Python Shell: ...
- git for windows 无法结束node进程(windows下杀进程)
问题 windows 系统下,如果用CMD命令行启动node服务,Ctrl + C 即可结束命令 git bash 用起来比命令行方便,但是Ctrl + C 并不会结束node服务,再次启动会报如下错 ...
- 【Atheros】无线网卡驱动性能测试工具pktgen的使用
前言:从12年开始做无线驱动相关的工作,到13年大概做了一年半,现在歇了快一年了,以免白学那么久,最近重新整理了一下当时的资料,写一点文章,这方面的帖子比较少,当时碰到过很多问题难以解决,我是用的li ...
- 计算机网络 --万维网www
万维网是一个分布式的超媒体系统,客户程序向服务器程序发出请求,服务器程序向客户程序送回客户所需要的万维网文档.万维网必须解决的几个问题:1.怎样标志分布在整个因特网上的万维网文档?答:万维网使用统一的 ...
- struts2中拦截器与过滤器之间的区别
首先是一张经典的struts2原理图 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标准的过滤器链 c) ...
- C# 自定义控件制作和使用实例(winform)(转)
本例是制作一个简单的自定义控件,然后用一个简单的测试程序,对于初学者来说,本例子比较简单,只能起到抛石引玉的效果. 我也是在学习当中,今后会将自己所学的逐步写出来和大家交流共享. 第一步:新建一个 ...
- 九度OJ 1004:Median
#include <stdio.h> #include <stdlib.h> #include <limits.h> #define N 1000000 int a ...
- Ubuntu PPPoE拨号上网指定网卡
Just follow these steps: Check that the ethernet cable is properly connected Open Terminal Run sudo ...