题解:P14469 [COCI 2025/2026 #1] 皇后 / Kraljica
InnitTimmer_ · · 题解
首先这道题先考虑 bfs 做法,我们发现对于数字之间的传送是不需要任何花费的,所以可以将他们的边权设为
因为我们第一次 bfs 到一个点就是最优答案,所以每个点规定经过一次,时间复杂度
代码比较难写,注意一些细节。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
bool Test_MLE_start;
constexpr int N=1001;
int _=1,n,m,sx,sy,fx,fy,x[10][2],y[10][2],dp[N][N];
char s[N][N];bool vis[N][N];
struct node {int x,y;};
deque<node> q;
inline int reads() {
int c=getchar(),x=0,f=1;
while(!isdigit(c)) {
if(c=='-') f=-1;
c=getchar();
}
while(isdigit(c)) {
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x*f;
}
inline void files() {
freopen("std.in","r",stdin);
freopen("std.out","w",stdout);
}
inline void clr() {
// Don't forget!
}
void bfs(int sx,int sy) {
memset(dp,0x3f,sizeof(dp));
q.push_back(node {sx,sy});
dp[sx][sy]=0;
while(!q.empty()) {
int idx=q.front().x,idy=q.front().y;
q.pop_front();
if(vis[idx][idy]) continue;
vis[idx][idy]=1;
for(int x=idx+1; x<=n; x++) {
int y=idy;
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int x=idx-1; x>=1; x--) {
int y=idy;
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int y=idy+1; y<=m; y++) {
int x=idx;
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int y=idy-1; y>=1; y--) {
int x=idx;
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int x=idx+1,y=idy+1; x<=n,y<=m; x++,y++) {
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int x=idx+1,y=idy-1; x<=n,y>=1; x++,y--) {
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int x=idx-1,y=idy+1; x>=1,y<=m; x--,y++) {
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
for(int x=idx-1,y=idy-1; x>=1,y>=1; x--,y--) {
if(x<1||x>n||y<1||y>m||s[x][y]=='#') break;
if(dp[x][y]>dp[idx][idy]+1){
dp[x][y]=min(dp[x][y],dp[idx][idy]+1);
q.push_back(node {x,y});
}
}
if(isdigit(s[idx][idy])) {
int p=s[idx][idy]-'0',px,py;
if(idx==x[p][0]&&idy==y[p][0]) px=x[p][1],py=y[p][1];
else px=x[p][0],py=y[p][0];
dp[px][py]=min(dp[px][py],dp[idx][idy]);
q.push_front(node {px,py});
}
}
}
bool Test_MLE_end;
signed main() {
// printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0);
// files();
// _=reads();
while(_--) {
clr();
n=reads(),m=reads();
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
cin>>s[i][j];
if(s[i][j]=='S') sx=i,sy=j;
else if(s[i][j]=='E') fx=i,fy=j;
else if(isdigit(s[i][j])) {
int p=s[i][j]-'0';
if(!x[p][0]) x[p][0]=i;
else x[p][1]=i;
if(!y[p][0]) y[p][0]=j;
else y[p][1]=j;
}
}
}bfs(sx,sy);
if(dp[fx][fy]==0x3f3f3f3f) puts("-1");
else printf("%d\n",dp[fx][fy]);
}
return 0;
}
/*
5 5
S##..
##...
..#..
.....
.#..E
*/