题解 CF1063B 【Labyrinth】

ouuan

2018-10-14 22:00:16

Solution

这题有向左最大步数和向右最大步数两个约束,所以很烦。能不能只有一个约束呢?这个时候往往要观察几个约束条件之间的关系。 **1.向左走的步数-向右走的步数=起点横坐标-终点横坐标** 有了这个式子,就可以用向左走的步数同时表示向右走的步数。 **2.向左走的步数越多,向右走的步数越多** 这个条件是可以由上面那个式子推来的,它的作用是保证了向左走的步数最少时一定是全局最优解。 所以整个问题被转化成了只用管向左步数的01最短路,用SPFA即可解决,计算答案时满足**向左步数<=向左最大步数&&向左步数+横坐标之差<=最大向右步数**就计入答案。 参考代码: ``` #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; typedef pair<int,int> pii; const int N=2010; const int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; int n,m,r,c,x,y,dis[N][N],ans; bool g[N][N],inq[N][N]; char s[N]; queue<pii> q; int main() { int i,j,tx,ty; pii t; memset(dis,0x3f,sizeof(dis)); scanf("%d%d%d%d%d%d",&n,&m,&r,&c,&x,&y); for (i=1;i<=n;++i) { scanf("%s",s); for (j=1;j<=m;++j) { if (s[j-1]=='.') { g[i][j]=true; } } } dis[r][c]=0; q.push(pii(r,c)); while (!q.empty()) { t=q.front(); q.pop(); inq[t.first][t.second]=false; for (i=0;i<4;++i) { tx=t.first+dir[i][0]; ty=t.second+dir[i][1]; if (g[tx][ty]&&dis[tx][ty]>dis[t.first][t.second]+(i==0)) { dis[tx][ty]=dis[t.first][t.second]+(i==0); if (!inq[tx][ty]) { inq[tx][ty]=true; q.push(pii(tx,ty)); } } } } for (i=1;i<=n;++i) { for (j=1;j<=m;++j) { if (g[i][j]&&dis[i][j]<=x&&dis[i][j]+j-c<=y) { ++ans; } } } printf("%d",ans); return 0; } ```