ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#402 | #60. 「NOIP2013」华容道 | ryp | 100 | 278ms | 3692kb | C++14 | 4.3kb | 2025-04-23 12:51:12 | 2025-04-23 12:51:13 |
answer
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define N 35
int rd()
{
int f=1,s=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();}
return f*s;
}
const int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
//下上右左
int n,m,q;
int mp[N][N];
int ex,ey,sx,sy,tx,ty;
int cnt[N][N][5];
bool check(int xx,int yy)
{
if(xx<=0||xx>n||yy<=0||yy>m||mp[xx][yy]==0) return 0;
return 1;
}
int tot;
struct node{
int x,y,stp/*广搜的时候用 存步数*/;
};
bool vis[N][N],mark[N*N]/*spfa的标记数组*/;
vector<pair<int,int> >G[N*N];
void add(int u,int v,int w)
{
G[u].push_back(make_pair(v,w));
}
int bfs(int ax,int ay,int bx,int by,int cx,int cy)
{//a到b不经过点c的最短距离
if(ax==bx&&ay==by) return 0;//起点就是终点
memset(vis,0,sizeof(vis));
queue<node>Q;
while(!Q.empty()) Q.pop();
node s;s.x=ax,s.y=ay,s.stp=0;
Q.push(s);
vis[ax][ay]=1;
while(!Q.empty())
{
node now=Q.front();Q.pop();
if(now.x==bx&&now.y==by) return now.stp;
for(int i=0;i<4;i++)
{
node nxt;
nxt.x=now.x+dx[i],nxt.y=now.y+dy[i];
if(!check(nxt.x,nxt.y)) continue;
if(nxt.x==cx&&nxt.y==cy) continue;
if(vis[nxt.x][nxt.y]) continue;
nxt.stp=now.stp+1;
Q.push(nxt);
vis[nxt.x][nxt.y]=1;
}
}
return INF;//不能到达
}
void Init()
{
//cnt存状态标号 spfa的时候是把点看成状态 用边来表示状态的转移
//[i][j][k]是表示开始的那个点的坐标是(i,j) 空格在它的k方向
tot=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++)
if(mp[i][j]&&check(i+dx[k],j+dy[k]))
cnt[i][j][k]=++tot;//给状态标号 没有标号的就是不可行的状态
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++)
if(cnt[i][j][k])
{
int tmp;
if(k==0) tmp=1;
if(k==1) tmp=0;
if(k==2) tmp=3;
if(k==3) tmp=2;
add(cnt[i][j][k],cnt[i+dx[k]][j+dy[k]][tmp],1);
//连单向边就可以了 后面会遍历到旁边状态连回来的
//交换空白格子和起点格子 只需要一步
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++)
for(int p=0;p<4;p++)//枚举起点格子相邻一圈的两个格子
if(k!=p&&cnt[i][j][k]&&cnt[i][j][p])
add(cnt[i][j][k],cnt[i][j][p],bfs(i+dx[k],j+dy[k],i+dx[p],j+dy[p],i,j));
//可以起点格子不动 而空白格子绕着它转(换方向)
//如果用起点格子自己换方向 可能没那么优秀因为要绕一绕
//而且起点格子有可能会跑到一个离终点的地方去了 更不优
//而只动空白格子可能会优秀一些 因为空白格子最优(到处都是活动格子)只用走2~4步
//经过其他格子没有任何影响 因为都是1 只是空白格子变了而已
//而经过起点格子则会改变起点格子的坐标
}
int dis[N*N];
int spfa()
{
queue<int>Q;
while(!Q.empty()) Q.pop();
if(sx==tx&&sy==ty) return 0;
memset(dis,INF,sizeof(dis));
memset(mark,0,sizeof(mark));
for(int k=0;k<4;k++)
{//空格先走到起点的四周 初始状态 以空格从起点四周开始
if(cnt[sx][sy][k])
{
dis[cnt[sx][sy][k]]=bfs(ex,ey,sx+dx[k],sy+dy[k],sx,sy);
Q.push(cnt[sx][sy][k]);
mark[cnt[sx][sy][k]]=1;
}
}
while(!Q.empty())
{
int u=Q.front();Q.pop();
mark[u]=0;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].first,w=G[u][i].second;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!mark[v])
{
Q.push(v);
mark[v]=1;
}
}
}
}
//空格在哪里不用管 起点格子到了就可以
//从空格在起点格子四周随便哪个地方的状态到空格在终点格子四周随便哪个地方的状态
int res=INF;
for(int k=0;k<4;k++)
if(cnt[tx][ty][k])
res=min(res,dis[cnt[tx][ty][k]]);
if(res==INF) return -1;//走不到
return res;
}
int main()
{
n=rd(),m=rd(),q=rd();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
mp[i][j]=rd();
Init();
while(q--)
{
ex=rd(),ey=rd(),sx=rd(),sy=rd(),tx=rd(),ty=rd();
printf("%d\n",spfa());
}
return 0;
}
详细
小提示:点击横条可展开更详细的信息
Test #1:
score: 5
Accepted
time: 1ms
memory: 3336kb
input:
3 3 1 1 1 0 1 1 0 1 1 0 3 1 1 1 3 1
output:
7
result:
ok 1 number(s): "7"
Test #2:
score: 5
Accepted
time: 4ms
memory: 3400kb
input:
5 5 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 0 1 4 2 3 4 2 2
output:
13
result:
ok 1 number(s): "13"
Test #3:
score: 5
Accepted
time: 4ms
memory: 3532kb
input:
10 10 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 ...
output:
377
result:
ok 1 number(s): "377"
Test #4:
score: 5
Accepted
time: 3ms
memory: 3520kb
input:
3 3 1 0 1 1 1 1 0 1 1 1 2 1 3 1 1 3
output:
-1
result:
ok 1 number(s): "-1"
Test #5:
score: 5
Accepted
time: 3ms
memory: 3580kb
input:
5 5 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 0 1 1 1 1 1 1 0 1 1 2 4 1 1 4 2
output:
17
result:
ok 1 number(s): "17"
Test #6:
score: 5
Accepted
time: 3ms
memory: 3536kb
input:
10 10 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ...
output:
227
result:
ok 1 number(s): "227"
Test #7:
score: 5
Accepted
time: 2ms
memory: 3360kb
input:
10 20 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 ...
output:
1176 2279 44 1525 493
result:
ok 5 number(s): "1176 2279 44 1525 493"
Test #8:
score: 5
Accepted
time: 9ms
memory: 3556kb
input:
20 25 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
output:
15257 1418 2345 2025 6189
result:
ok 5 number(s): "15257 1418 2345 2025 6189"
Test #9:
score: 5
Accepted
time: 20ms
memory: 3528kb
input:
30 30 10 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
output:
71934 50048 77876 36822 3122 80641 -1 64554 65906 10638
result:
ok 10 numbers
Test #10:
score: 5
Accepted
time: 4ms
memory: 3480kb
input:
10 20 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 1 1 0 ...
output:
3060 3482 134 1288 -1
result:
ok 5 number(s): "3060 3482 134 1288 -1"
Test #11:
score: 5
Accepted
time: 4ms
memory: 3660kb
input:
20 25 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
output:
2638 13168 9091 12092 8525
result:
ok 5 number(s): "2638 13168 9091 12092 8525"
Test #12:
score: 5
Accepted
time: 17ms
memory: 3520kb
input:
30 30 10 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0...
output:
40970 -1 -1 20106 34048 21854 24476 -1 29970 15139
result:
ok 10 numbers
Test #13:
score: 5
Accepted
time: 11ms
memory: 3428kb
input:
10 20 400 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 ...
output:
1123 2979 3325 3580 3564 0 610 2931 2901 392 2959 2795 3118 3275 2267 157 2591 2070 3845 307 1553 10...
result:
ok 400 numbers
Test #14:
score: 5
Accepted
time: 18ms
memory: 3620kb
input:
20 25 450 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
output:
5813 -1 8039 10811 7533 7569 5511 -1 5270 11074 10284 1274 10828 7308 13396 -1 10352 -1 1094 -1 -1 1...
result:
ok 450 numbers
Test #15:
score: 5
Accepted
time: 34ms
memory: 3468kb
input:
30 30 500 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
output:
45430 42629 11500 34698 39003 3846 23838 59458 51409 58852 6824 2903 30391 3170 18108 19900 9158 770...
result:
ok 500 numbers
Test #16:
score: 5
Accepted
time: 35ms
memory: 3692kb
input:
30 30 500 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
output:
15504 45201 15725 -1 64549 -1 29634 14906 10102 39160 -1 7295 68621 14617 -1 5325 65849 47760 5322 2...
result:
ok 500 numbers
Test #17:
score: 5
Accepted
time: 7ms
memory: 3480kb
input:
10 20 400 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 ...
output:
1788 1997 2144 479 1241 792 2644 913 0 2956 -1 183 1358 2995 290 1082 1074 931 2962 2025 2211 1098 2...
result:
ok 400 numbers
Test #18:
score: 5
Accepted
time: 24ms
memory: 3444kb
input:
20 25 450 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ...
output:
2293 1107 227 4219 3227 4357 2254 5891 1300 -1 4163 2056 140 3164 -1 1750 2859 8118 1136 4098 3919 4...
result:
ok 450 numbers
Test #19:
score: 5
Accepted
time: 36ms
memory: 3596kb
input:
30 30 500 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
output:
6667 68635 16685 34236 66264 109 15972 12341 21211 7009 45547 29642 36831 7554 7186 36934 37614 2593...
result:
ok 500 numbers
Test #20:
score: 5
Accepted
time: 39ms
memory: 3468kb
input:
30 30 500 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 ...
output:
45435 36968 37705 15892 -1 45171 21764 19862 17735 330 44118 1999 -1 2643 8296 22118 24881 2899 1833...
result:
ok 500 numbers