一、题目
二、解法
把每一个位置拆成 6 6 6个点: 0 − 3 0-3 0−3分别代表球正在向上下左右四个方向滚动, 4 4 4代表球在该点但是没人持球, 5 5 5代表球在该点而且有人持球。下面详细讲一下建边的方法:
- 没人持球到有人持球,召唤离当前点最近的
工具人,这人不用考虑移动,因为一个人持球并踢开后就不可能再持球了,找这个最近的人就可以用 b f s bfs bfs - 某个方向到无人持球,边权为 0 0 0
- 某个方向继续滚动,边权为 A A A
- 有人持球到下一个位置继续持球,边权为 C C C
- 有人持球到踢出去(状态还是在当前点),边权为 B B B
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 505;
const int M = 260005;
#define int long long
#define pii pair<int,int>
#define fi first
#define se second
int read()
{
int num=0,flag=1;
char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
return num*flag;
}
int n,m,k,t,A,B,C,tot,f[6*M],dis[6*M],x[M],y[M],vis[N][N];
int dx[5]= {1,-1},dy[5]= {0,0,1,-1};
struct edge
{
int v,c,next;
} e[20*M];
struct node
{
int u,c;
bool operator < (const node &b) const
{
return c>b.c;
}
};
void bfs()
{
queue<pii> q;
memset(vis,-1,sizeof vis);
for(int i=1; i<=k; i++)
{
x[i]=read();
y[i]=read();
vis[x[i]][y[i]]=0;
q.push(make_pair(x[i],y[i]));
}
while(!q.empty())
{
pii t=q.front();
q.pop();
for(int i=0; i<4; i++)
{
int x=t.fi+dx[i],y=t.se+dy[i];
if(x>=0 && x<=n && y>=0 && y<=m && vis[x][y]==-1)
{
vis[x][y]=vis[t.fi][t.se]+1;
q.push(make_pair(x,y));
}
}
}
}
int id(int x,int y)
{
return x*(m+1)+y;
}
void add(int u,int v,int c)
{
e[++tot]=edge{v,c,f[u]},f[u]=tot;
}
void build()
{
t=(n+1)*(m+1);
for(int i=0; i<=n; i++)
for(int j=0; j<=m; j++)
{
add(id(i,j)+4*t,id(i,j)+5*t,C*vis[i][j]);
for(int k=0; k<4; k++)
{
int x=i+dx[k],y=j+dy[k];
add(id(i,j)+k*t,id(i,j)+4*t,0);
add(id(i,j)+5*t,id(i,j)+k*t,B);
if(!(x>=0 && x<=n && y>=0 && y<=m)) continue;
add(id(i,j)+k*t,id(x,y)+k*t,A);
add(id(i,j)+5*t,id(x,y)+5*t,C);
}
}
}
void dijk()
{
memset(dis,0x3f,sizeof dis);
priority_queue<node> q;
q.push(node{id(x[1],y[1])+5*t,0});
dis[id(x[1],y[1])+5*t]=0;
while(!q.empty())
{
node t=q.top();
q.pop();
if(t.c>dis[t.u]) continue;
for(int i=f[t.u]; i; i=e[i].next)
{
int v=e[i].v,c=e[i].c;
if(dis[v]>dis[t.u]+c)
{
dis[v]=dis[t.u]+c;
q.push(node{v,dis[v]});
}
}
}
printf("%lld\n",dis[id(x[k],y[k])+5*t]);
}
signed main()
{
n=read();
m=read();
A=read();
B=read();
C=read();
k=read();
bfs();
build();
dijk();
}