[APIO2013]机器人
Posted Tan_tan_tann
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[APIO2013]机器人相关的知识,希望对你有一定的参考价值。
机器人
题解
**卡常题
首先,由于一个机械人只能往 4 4 4个方向走,而每个点往一个方向走最终停留下来的点是固定的,我们可以考虑每个点往每个方向走走到的点先预处理出来,建个新图。
由于它要求只有编号连续的机械人在同一个节点上是才能够合并,所以我们可以考虑区间
d
p
dp
dp。
定义
d
p
l
,
r
,
i
,
j
dp_{l,r,i,j}
dpl,r,i,j表示编号区间为
[
l
,
r
]
[l,r]
[l,r]的机械人走到格子
(
i
,
j
)
(i,j)
(i,j)上时最小的代价,容易得到
d
p
dp
dp转移方程式:
d
p
l
,
r
,
i
,
j
=
min
k
=
l
r
−
1
(
d
p
l
,
k
,
i
,
j
+
d
p
k
+
1
,
r
,
i
,
j
,
d
p
l
,
r
,
i
,
j
)
dp_{l,r,i,j}=\\min_{k=l}^{r-1}\\left(dp_{l,k,i,j}+dp_{k+1,r,i,j},dp_{l,r,i,j}\\right)
dpl,r,i,j=k=lminr−1(dpl,k,i,j+dpk+1,r,i,j,dpl,r,i,j)
d
p
l
,
r
,
t
o
i
,
j
,
k
=
min
(
d
p
l
,
r
,
t
o
i
,
j
,
k
,
d
p
l
,
r
,
i
,
j
+
1
)
dp_{l,r,to_{i,j,k}}=\\min\\left(dp_{l,r,to_{i,j,k}},dp_{l,r,i,j}+1\\right)
dpl,r,toi,j,k=min(dpl,r,toi,j,k,dpl,r,i,j+1)
第一个式子主要涉及同一个节点上区间的合并,而第二个式子这是机械人在图上得移动。
对于第一个式子,直接转移即可。
对于第二个式子,这是一个多元的最短路,我们可以考虑用
S
P
F
A
SPFA
SPFA来进行维护。
直接对于每个
(
l
,
r
)
(l,r)
(l,r)暴力进行区间转移与最短路即可。
但不幸的时,直接暴力
S
P
F
A
SPFA
SPFA是会
T
T
T飞的,考虑优化。
然后我们就要开始加上一些稀奇古怪的优化了。
L
L
L
LLL
LLL与
S
L
F
SLF
SLF优化当然是必须的,不过实际上
L
L
L
LLL
LLL好像没多大用 (指算法)。
我们在将
S
P
F
A
SPFA
SPFA的起始点加入队列时需要先将其按
d
p
l
,
r
,
i
,
j
dp_{l,r,i,j}
dpl,r,i,j的值排序,再加入队列,以保证最开始的起点竟可能的小。
然后就是
S
P
F
A
SPFA
SPFA选起点时可以选择队列前两个点中较小的一个,将大的放回队首。
注意
L
L
L
LLL
LLL优化记录
s
u
m
sum
sum时要开
l
o
n
g
l
o
n
g
longlong
longlong,否则会在
u
o
j
uoj
uoj上挂掉。
然后,统计答案即可。
时间复杂度达到了惊人的
O
(
n
3
h
w
+
n
2
(
h
w
)
2
(
?
)
)
O\\left(n^3hw+n^2(hw)^2(?)\\right)
O(n3hw+n2(hw)2(?))。
话说这能过真的正常吗?
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int orG=3,invG=332748118;
const int lim=300000;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
int dx[5]={1,0,-1,0},dy[5]={0,1,0,-1};
int n,w,h,ans,l,r,to[MAXN][5];
int dp[12][12][MAXN];char maze[505][505];
int head,tail,stak,q[MAXN],sta[MAXN];
bool vis[5][505][505],inq[MAXN];
inline int Hash(pii x){return (x.fir-1)*w+x.sec;}
int dosaka(int x,int y,int f){
int id=Hash(mkpr(x,y));if(vis[f][x][y])return to[id][f];
to[id][f]=Hash(mkpr(-1,-1));vis[f][x][y]=1;int tf=f;
if(maze[x][y]=='A')f=f>2?f-3:f+1;
if(maze[x][y]=='C')f=f>0?f-1:f+3;
int tx=x+dx[f],ty=y+dy[f];
if(tx<1||ty<1||tx>h||ty>w)return to[id][tf]=id;
if(maze[tx][ty]=='x')return to[id][tf]=id;
return to[id][tf]=dosaka(tx,ty,f);
}
bool cmp(int x,int y){return dp[l][r][x]<dp[l][r][y];}
inline int adhead(){int tp=head;head++;if(head>lim)head=1;return tp;}
inline int adtail(){int tp=tail;tail++;if(tail>lim)tail=1;return tp;}
inline int rehead(){head--;if(head<1)head=lim;return head;}
signed main(){
read(n);read(w);read(h);ans=INF;
for(reg int i=1;i<=h;++i)scanf("\\n%s",maze[i]+1);
for(int l=以上是关于[APIO2013]机器人的主要内容,如果未能解决你的问题,请参考以下文章