[NOIP2013]华容道
【题目描述】
这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街。考后想想也是,数据这么小一定有他的道理。
首先由于是最小步数,所以BFS没跑了。那么我们大可把这道题分为两部分,首先先把白格子移到目标棋子附近,然后再把目标棋子移过去。第一步是很容易的,随便BFS一下就好了,关键是第二步。由于q不小,我们不可能每次询问都直接爆搜,但由于棋盘并不会发生本质改变,我们可以对一些东西进行预处理。
那每次询问时不变的是什么呢,我们求第二步时需要的又是什么呢?
首先我们可以明确的是一个棋子得以移动一定是它移动的目标上是空的,而我们只有一个空格子,所以一旦我们确定了空格子的位置整个棋盘的状态就明了了,所以我们要处理的是当白格子在哪个位置时我想把当前棋子移到上下左右某一位置所要花费的最少步数,那么我们真的需要开5维去表示这一状态吗?不必,四维就够了,对于白格子从之前道这个点附近其实本质和第一步无异,而在我们执行第二步时白格子在每次转移完一定是在目标棋子的上下左右位置,所以我们只需要处理出来目标棋子在当前格子时白格子在他上下左右时他向上下左右移动所耗费的步数即可。
然后,对于每一次询问,我们可以把每个点拆成四个,即白格子在这个点上下左右时的最小步数,慢慢搞即可。
对了,提醒一下,对于某个格子进行处理的时候一定不能通过该点进行更新。
1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<map>
7 #include<queue>
8 #include<string>
9 #include<cmath>
10 using namespace std;
11 int n,m,q,a[40][40],zy[5][2],dis[40][40];
12 struct no{int x,y,k;};
13 bool check(int x,int y,int z){
14 if(x+zy[z][0]!=0&&x+zy[z][0]!=n+1&&y+zy[z][1]!=0&&y+zy[z][1]!=m+1&&a[x+zy[z][0]][y+zy[z][1]]) return 1;
15 return 0;
16 }
17 bool fw[40][40],f2[40][40];
18 int f[40][40][5][5];
19 void bfs1(int ax,int by){
20 memset(dis,0x3f,sizeof(dis));
21 memset(fw,0,sizeof(fw));
22 queue<no> q1;
23 no aa;
24 aa.x=ax,aa.y=by;
25 dis[ax][by]=0;
26 q1.push(aa);
27 fw[ax][by]=1;
28 while(!q1.empty())
29 {
30 no t=q1.front();
31 q1.pop();
32 int x=t.x,y=t.y;
33 for(int i=1;i<=4;i++)
34 {
35 int xx=x+zy[i][0],yy=y+zy[i][1];
36 if(xx==0||xx==n+1||yy==0||yy==m+1) continue;
37 if(!a[xx][yy]) continue;
38 if(f2[xx][yy]) continue;
39 if(dis[xx][yy]>dis[x][y]+1)
40 {
41 dis[xx][yy]=dis[x][y]+1;
42 if(!fw[xx][yy])
43 {
44 fw[xx][yy]=1;
45 no bb;
46 bb.x=xx,bb.y=yy;
47 q1.push(bb);
48 }
49 }
50 }
51 }
52 }
53 bool rd[40][40][4];
54 int dis2[40][40][5];
55 void spfa(int ax,int by){
56 memset(rd,0,sizeof(rd));
57 no aa;
58 queue<no> q1;
59 aa.x=ax,aa.y=by;
60 if(check(ax,by,1))
61 {
62 aa.k=1;
63 q1.push(aa);
64 rd[ax][by][1]=1;
65 }
66 if(check(ax,by,2))
67 {
68 aa.k=2;
69 q1.push(aa);
70 rd[ax][by][2]=1;
71 }
72 if(check(ax,by,3))
73 {
74 aa.k=3;
75 q1.push(aa);
76 rd[ax][by][3]=1;
77 }
78 if(check(ax,by,4))
79 {
80 aa.k=4;
81 q1.push(aa);
82 rd[ax][by][4]=1;
83 }
84 while(!q1.empty())
85 {
86 no bb=q1.front();q1.pop();
87 int x=bb.x,y=bb.y,k=bb.k;
88 rd[x][y][k]=0;
89 if(check(x,y,1)&&dis2[x-1][y][2]>dis2[x][y][k]+f[x][y][1][k]&&f[x][y][1][k]!=-1)
90 {
91 dis2[x-1][y][2]=dis2[x][y][k]+f[x][y][1][k];
92 if(!rd[x-1][y][2])
93 {
94 rd[x-1][y][2]=1;
95 no cc;
96 cc.x=x-1,cc.y=y,cc.k=2;
97 q1.push(cc);
98 }
99 }
100 if(check(x,y,2)&&dis2[x+1][y][1]>dis2[x][y][k]+f[x][y][2][k]&&f[x][y][2][k]!=-1)
101 {
102 dis2[x+1][y][1]=dis2[x][y][k]+f[x][y][2][k];
103 if(!rd[x+1][y][1])
104 {
105 rd[x+1][y][1]=1;
106 no cc;
107 cc.x=x+1,cc.y=y,cc.k=1;
108 q1.push(cc);
109 }
110 }
111 if(check(x,y,3)&&dis2[x][y-1][4]>dis2[x][y][k]+f[x][y][3][k]&&f[x][y][3][k]!=-1)
112 {
113 dis2[x][y-1][4]=dis2[x][y][k]+f[x][y][3][k];
114 if(!rd[x][y-1][4])
115 {
116 rd[x][y-1][4]=1;
117 no cc;
118 cc.x=x,cc.y=y-1,cc.k=4;
119 q1.push(cc);
120 }
121 }
122 if(check(x,y,4)&&dis2[x][y+1][3]>dis2[x][y][k]+f[x][y][4][k]&&f[x][y][4][k]!=-1)
123 {
124 dis2[x][y+1][3]=dis2[x][y][k]+f[x][y][4][k];
125 if(!rd[x][y+1][3])
126 {
127 rd[x][y+1][3]=1;
128 no cc;
129 cc.x=x,cc.y=y+1,cc.k=3;
130 q1.push(cc);
131 }
132 }
133 }
134 }
135 int main(){
136 memset(f,-1,sizeof(f));
137 scanf("%d%d%d",&n,&m,&q);
138 for(int i=1;i<=n;i++)
139 for(int j=1;j<=m;j++)
140 scanf("%d",&a[i][j]);
141 zy[1][0]=-1,zy[2][0]=1;
142 zy[3][1]=-1,zy[4][1]=1;
143 for(int i=1;i<=n;i++)
144 {
145 for(int j=1;j<=m;j++)
146 {
147 if(!a[i][j]) continue;
148 f2[i][j]=1;
149 for(int k=1;k<=4;k++)
150 {
151 if(check(i,j,k))
152 {
153 bfs1(i+zy[k][0],j+zy[k][1]);
154 for(int l=1;l<=4;l++)
155 {
156 if(check(i,j,l)&&dis[i+zy[l][0]][j+zy[l][1]]!=dis[0][0])
157 f[i][j][l][k]=dis[i+zy[l][0]][j+zy[l][1]]+1;
158 }
159 }
160 }
161 f2[i][j]=0;
162 }
163 }
164
165 for(int i=1;i<=q;i++)
166 {
167 int ex,ey,sx,sy,tx,ty;
168 scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
169 if(tx==sx&&ty==sy)
170 {
171 printf("0\n");
172 continue;
173 }
174 memset(dis2,0x3f,sizeof(dis2));
175 memset(f2,0,sizeof(f2));
176 f2[sx][sy]=1;
177 bfs1(ex,ey);
178 bool yx=0;
179 for(int j=1;j<=4;j++)
180 {
181 if(check(sx,sy,j)&&dis[sx+zy[j][0]][sy+zy[j][1]]!=dis[0][0])
182 {
183 yx=1;
184 dis2[sx][sy][j]=dis[sx+zy[j][0]][sy+zy[j][1]];
185 }
186 }
187 if(!yx)
188 {
189 printf("-1\n");
190 continue;
191 }
192 spfa(sx,sy);
193 int ans=0x7fffffff;
194 for(int j=1;j<=4;j++)
195 ans=min(ans,dis2[tx][ty][j]);
196 if(ans==0x7fffffff||ans==dis2[0][0][0])
197 {
198 printf("-1\n");
199 continue;
200 }
201 else
202 printf("%d\n",ans);
203 }
204 return 0;
205 }
View Code