\(\\\)
\(Description\)
给出一个四联通的\(N\times M\) 网格图和起点。图中有一些位置是障碍物。
现在上下移动步数不限,向左至多走 \(a\) 步,向右至多走 \(b\) 步,求从起点出发能到达多少个空地。
- \(N,M\le 2000\)
\(\\\)
\(Solution\)
爷们太神了......
开始的想法是直接跑最短路, \(dist\) 为横向移动总步数。
后来发现矛盾在于,如果到一个格子向左走的步数较少,向右走的步数较多,和这种情况反过来,无法确定那种更优,进而无法确定用那种状态更新接下来的点。
然后听爷们讲了好久听懂了正确性证明。考虑要从起点 U 到达 V 这个格子,它横向的差值为 \(2\) 是固定的。
也就是说,任何一个合法的方案向左走的步数减掉向右走的步数都应该等于 \(2\)。
那么这种矛盾不存在了。因为向左向右的步数会同时增长,否则一定不会到达这个目标点。

然后就愉快上最短路,根据\(Dij\) 的原理,循环次数就是访问的点数。
\(\\\)
\(Code\)
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 2010 #define R register #define gc getchar #define inf 2000000000 using namespace std; typedef long long ll; inline ll rd(){ ll x=0; bool f=0; char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();} return f?-x:x; } int n,m,lx,rx,ux,uy,ans; bool mp[N][N],vis[N][N]; struct dist{ int x,y,l,r,sum; friend operator < (const dist &x,const dist &y){ return x.sum>y.sum; } }dis[N][N]; priority_queue<dist> q; int main(){ n=rd(); m=rd(); ux=rd(); uy=rd(); lx=rd(); rx=rd(); char c=gc(); for(R int i=1;i<=n;++i) for(R int j=1;j<=m;++j){ while(c!='.'&&c!='*') c=gc(); mp[i][j]=(c=='.'); c=gc(); dis[i][j].x=i; dis[i][j].y=j; dis[i][j].l=dis[i][j].r=dis[i][j].sum=inf; } dis[ux][uy].l=dis[ux][uy].r=dis[ux][uy].sum=0; q.push(dis[ux][uy]); while(!q.empty()){ dist x=q.top(); q.pop(); if(vis[x.x][x.y]) continue; vis[x.x][x.y]=1; ++ans; if(mp[x.x+1][x.y]){ if(dis[x.x+1][x.y].sum>x.sum){ dis[x.x+1][x.y].l=x.l; dis[x.x+1][x.y].r=x.r; dis[x.x+1][x.y].sum=x.sum; q.push(dis[x.x+1][x.y]); } } if(mp[x.x-1][x.y]){ if(dis[x.x-1][x.y].sum>x.sum){ dis[x.x-1][x.y].l=x.l; dis[x.x-1][x.y].r=x.r; dis[x.x-1][x.y].sum=x.sum; q.push(dis[x.x-1][x.y]); } } if(mp[x.x][x.y-1]&&x.l<lx){ if(dis[x.x][x.y-1].sum>x.sum+1){ dis[x.x][x.y-1].l=x.l+1; dis[x.x][x.y-1].r=x.r; dis[x.x][x.y-1].sum=x.sum+1; q.push(dis[x.x][x.y-1]); } } if(mp[x.x][x.y+1]&&x.r<rx){ if(dis[x.x][x.y+1].sum>x.sum+1){ dis[x.x][x.y+1].l=x.l; dis[x.x][x.y+1].r=x.r+1; dis[x.x][x.y+1].sum=x.sum+1; q.push(dis[x.x][x.y+1]); } } } printf("%d\n",ans); return 0; }
来源:https://www.cnblogs.com/SGCollin/p/9792791.html