亚瑟王的宫殿:比较 tricky 的图论。

图论做法

思路

因为是无向图,所以考虑一个经典 trick,把所有点到集合点的距离之和化为集合点到其他所有点的位置之和,就可以从集合点做单源最短路了。

于是我们枚举集合点,从集合点 BFS 一遍,然后算出答案。

但是这题还有国王,有一个骑士要去接国王去集合点,于是考虑在枚举集合点后,继续枚举是哪个骑士去接国王。

那么某个骑士去接国王的代价如何计算呢?显然,骑士和国王必将在某一个点处会合,并且对于每一个会合位置,国王走的步数是确定的。因此我们可以把接国王的代价看作骑士移动的代价,也就是建立分层图,一层代表还没接到国王,一层代表接到了国王。每一层内部的边权都是 \(1\),只有两层之间的边权为国王到某个点的代价。于是我们就可以用 dijkstra 快速计算骑士接到国王再到集合点的代价了。注意这一部分也要从集合点开始跑单源最短路。

时间复杂度 \(O(n^2m^2\log nm)\)。

注意特判只有一个国王以及集合点无法到达的情况。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
using piii=pair<int,pair<int,pi> >;
int n,m,kx,ky,ax[2005],ay[2005],s;
int d[50][50],dk[50][50],dis[2][50][50],ans=0x3f3f3f3f;
int gox[]={1,1,2,2,-1,-1,-2,-2};
int goy[]={2,-2,1,-1,2,-2,1,-1};
int gokx[]={0,0,1,1,1,-1,-1,-1};
int goky[]={1,-1,0,1,-1,0,1,-1};
bool legal(int x,int y){return (1<=x&&x<=n&&1<=y&&y<=m);}
void bfs_knight(int x,int y)
{
memset(d,0x3f,sizeof(d));
d[x][y]=0;
queue<pi>q;
q.push({x,y});
while(!q.empty())
{
pi now=q.front();
q.pop();
int nx=now.fi,ny=now.se;
for(int i=0;i<8;i++)
{
int tx=nx+gox[i],ty=ny+goy[i];
if(legal(tx,ty)&&d[tx][ty]>=0x3f3f3f3f)
{
d[tx][ty]=d[nx][ny]+1;
q.push({tx,ty});
}
}
}
}
void bfs_king(int x,int y)
{
memset(dk,0x3f,sizeof(dk));
dk[x][y]=0;
queue<pi>q;
q.push({x,y});
while(!q.empty())
{
pi now=q.front();
q.pop();
int nx=now.fi,ny=now.se;
for(int i=0;i<8;i++)
{
int tx=nx+gokx[i],ty=ny+goky[i];
if(legal(tx,ty)&&dk[tx][ty]>=0x3f3f3f3f)
{
dk[tx][ty]=dk[nx][ny]+1;
q.push({tx,ty});
}
}
}
}
void dijkstra(int x,int y)
{
priority_queue<piii,vector<piii>,greater<piii> >q;
memset(dis,0x3f,sizeof(dis));
dis[0][x][y]=0;
q.push({0,{0,{x,y}}});
while(!q.empty())
{
piii now=q.top();
q.pop();
int lv=now.se.fi,nx=now.se.se.fi,ny=now.se.se.se;
for(int i=0;i<8;i++)
{
int tx=nx+gox[i],ty=ny+goy[i];
if(legal(tx,ty)&&dis[lv][tx][ty]>dis[lv][nx][ny]+1)
{
dis[lv][tx][ty]=dis[lv][nx][ny]+1;
q.push({dis[lv][tx][ty],{lv,{tx,ty}}});
}
}
if(lv==0)
{
if(dis[1][nx][ny]>dis[0][nx][ny]+dk[nx][ny])
{
dis[1][nx][ny]=dis[0][nx][ny]+dk[nx][ny];
q.push({dis[1][nx][ny],{1,{nx,ny}}});
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
char c;
int x,y;
cin>>c>>x;
y=c-'A'+1;
kx=x,ky=y;
while(cin>>c>>x){ax[s+1]=x,ay[s+1]=c-'A'+1;s++;}
if(s==0)
{
cout<<0;
return 0;
}
bfs_king(kx,ky);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
bool ilg=0;
int res=0x3f3f3f3f,tot=0;
bfs_knight(i,j);
dijkstra(i,j);
for(int k=1;k<=s;k++)
{
tot+=d[ax[k]][ay[k]];
if(d[ax[k]][ay[k]]>=0x3f3f3f3f/2){ilg=1;break;}
}
if(ilg)continue;
for(int k=1;k<=s;k++)res=min(res,tot-d[ax[k]][ay[k]]+dis[1][ax[k]][ay[k]]);
ans=min(ans,res);
}
}
cout<<ans;
return 0;
}

搜索做法

比较没道理,但凡这题不限制行列的个数,把 \(nm\) 再加大点,都不至于让这种做法过去。但是这种做法还是有点意义的。

同样是枚举集合点。这次我们考虑骑士接国王最多要花费多少步。显然,因为棋盘很小,所以最多不会超过 \(10\) 步就能接到国王。这当然不是一个准确的下界,只是这样取比较保险,洛谷上的题解大多都取少了,可以被 hack 掉。

于是我们枚举国王走 \(10\) 步以内到的点,然后像上面一样暴力做就好了。

时间复杂度 \(O(n^2m^2\times 100)\)。

代码没写。

Luogu P1930 亚瑟王的宫殿 题解 [ 蓝 ] [ 分层图最短路 ] [ 枚举 ]的更多相关文章

  1. 洛谷P1930 亚瑟王的宫殿 Camelot

    P1930 亚瑟王的宫殿 Camelot 19通过 53提交 题目提供者JOHNKRAM 标签USACO 难度提高+/省选- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 很久以前,亚瑟王和 ...

  2. 洛谷 P1930 亚瑟王的宫殿 Camelot

    传送门 题目大意:棋盘有骑士有王,让所有点跳到一个点,求所有棋子跳的步数和,和最小. 题解:bfs+枚举 王的人生: 1):自己走到聚集点 2):某个骑士来到王这里,两个棋子一起到聚集点 3):王走几 ...

  3. 【题解】P3645 [APIO2015]雅加达的摩天楼(分层图最短路)

    [题解]P3645 [APIO2015]雅加达的摩天楼(分层图最短路) 感觉分层图是个很灵活的东西 直接连边的话,边数是\(O(n^2)\)的过不去 然而我们有一个优化的办法,可以建一个新图\(G=( ...

  4. USACO Training3.3亚瑟王的宫殿【搜索】By cellur925

    题目传送门 因为太蒟了,所以参考了dalao@zbtrs ==    对此表示感谢并侵删. 看起来我们就知道这是搜索题. 最后的情况分两种:有骑士背国王/国王自食其力走到集合点. 首先,我们不知道大家 ...

  5. BZOJ 2763 飞行路线(分层图最短路)题解

    题意:中文题意不解释... 思路:分层图最短路,我们再开一维用来表示当前用了多少次免费次数,dis[i][j]就表示到达i点用了j次免费的最短路,有点DP的感觉. 当个模板用 参考:分层图最短路 代码 ...

  6. 【学习笔记/题解】分层图/[JLOI2011]飞行路线

    题目戳我 \(\text{Solution:}\) 关于分层图: 一般用于处理:给你\(k\)次机会对边权进行修改的最短路问题. 算法流程: 建立出\(k\)层图,对应进行\(k\)次操作后的局面. ...

  7. 洛谷 P3239 / loj 2112 [HNOI2015] 亚瑟王 题解【期望】【DP】

    ???看不懂的期望DP 题目描述 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂亮.众所周知,亚 ...

  8. P3239 [HNOI2015]亚瑟王——概率DP

    题面:亚瑟王 最近考试考期望很自闭啊,没做过这种类型的题,只能现在练一练: 所谓期望,就是状态乘上自己的概率:对于这道题来说,我们要求的是每张牌的伤害乘上打出的概率的和: 当然不是直接乘,因为给的是每 ...

  9. 洛谷P3239 [HNOI2015]亚瑟王

    题目描述 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑.他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂亮.众所周知,亚瑟王是一个看脸的游戏,技能 ...

  10. BZOJ 4008 【HNOI2015】 亚瑟王

    题目链接:亚瑟王 这道题好神啊TAT--果然我的dp还是太弱了-- 一开始想了半天的直接dp求期望,结果最后WA的不知所云-- 最后去翻了题解,然后发现先算概率,再求期望--新姿势\(get\). 我 ...

随机推荐

  1. 分布式事务之dtm

    github: https://github.com/dtm-labs/dtm 本人使用场景, 目前微服务中存在的用户服务, 商品服务,订单服务, 支付服务, 在进行下单操作的时候,需要创建订单并扣减 ...

  2. python开发包之远程隧道链接sshtunnel

    缘起: 公司很多的数据库的链接都是本地连接或者指定ip地址可以访问, 如果你没有该ip权限, 但是你可以登录该数据库所在的服务器, 这个时候就可以使用ssh链接上这个服务器,以此为跳板进行数据库的链接 ...

  3. Kibana之基本使用

    介绍kibana经常使用的功能 查询: # 查询内容不为空的数据,并返回总数量 GET mp_article/_search?rest_total_hits_as_int=true { "q ...

  4. 【JS篇】控制子集超过一定数量开始轮播

    [JS篇]控制子集超过一定数量开始轮播, 这个是很早的时候的一个效果了,经过代码的不断迭代升级修改,现在是最封装的一版本,通过面向对象传参数,适用于任何一个需要放置 数量达到一定条件后可执行的函数 / ...

  5. 鸿蒙UI开发快速入门 —— part09: 应用级状态管理LocalStorage & AppStorage

    1.说在前面的话 前面几个章节中介绍的装饰器(@State.@Props.@Link.@Provide.@Consume.@Observed.@ObjectLink)仅能在页面内,即一个组件树上共享状 ...

  6. openEuler欧拉安装Docker

    ​1. dnf配置 # 更新镜像源缓存 dnf makecache # 修改chrony时间同步配置 sed -i 's/pool pool.ntp.org iburst/pool ntp.aliyu ...

  7. Datadog发布云成本现状报告:83%的容器支出被闲置资源浪费

    原文链接:https://www.datadoghq.com/state-of-cloud-costs/ 编译:CloudPilot AI 尽管灵活多样的云服务为云成本优化提供了诸多机会,但企业在提升 ...

  8. 逍遥模拟器+Fiddler抓包 (附带软件)

    获取软件地址: 链接:https://pan.baidu.com/s/1zE9AECWOZlw_VDVMAnkBhQ?pwd=c0kq 提取码:c0kq 一.逍遥模拟器安装 1. 安装逍遥模拟器: 2 ...

  9. sed 指定行后或行前插入

    sed 功能非常强大,这里主要列出一些工作中常用到的举例,以后再追加 示例文本 example.cfg Config = { a = 1, b = 1024, c = { ErrLevel = 4, ...

  10. 从 $PGDATA 到文件组:深入解析 PostgreSQL 与 SQL Server 的存储策略

    从 $PGDATA 到文件组:深入解析 PostgreSQL 与 SQL Server 的存储策略 在数据库领域,数据存储和管理的效率与可靠性是决定系统性能.可扩展性和易于管理的关键因素.Postgr ...