Luogu P2243 电路维修 双端队列BFS
当转移的代价是0和一个分明不同的权值时,可以用双端队列BFS去跑(你跑最短路也没问题。。QWQ)
而对于这道题,边旋转代价是1,不旋转代价是0;可以直接建图最短路,也可以跑BFS
这个题建图很有意思:如果是' \ '就在mp上记录:1,反之 ' / '在上面记录为0
至于如何用:如果一个点在左上,一个点在右下,那么把mp取个非就是代价,即 \ 在mp中为1,我们用时要把它变成0,而 / 在mp中为0,用的时候变成1
如果一个点在右上,一个点在左下,那么代价就是mp的值
剩下就直接BFS就好了。。注意方向的常量数组,别写错,是向四个角扩展,而不是上下左右QWQ写到最后才发现。。
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #define P pair<int,int> #define PP pair<pair<int,int>,pair<int,int> > #define mkp make_pair #define R register int const int dx[]={-1,1,-1,1},dy[]={1,-1,-1,1}; using namespace std; const int M=550; int t,r,c; int d[M][M]; bool vis[M][M],mp[M][M]; char s[M]; deque<PP > q; inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline bool ckpos(int x,int y) {return x<1||y<1||x>r+1||y>c+1; } inline int w(int x,int xx,int y,int yy) { if((xx<x&&yy<y)||(xx>x&&yy>y)) return !mp[min(x,xx)][min(y,yy)]; else return mp[min(x,xx)][min(y,yy)]; } inline void bfs() { mp[0][0]=1; P u=mkp(0,0),v=mkp(1,1); q.push_back(mkp(u,v)); d[0][0]=0; while(q.size()) { PP t=q.front(); q.pop_front(); P u=t.first; P v=t.second; R xx=u.first,yy=u.second,x=v.first,y=v.second; if(vis[x][y]) continue; vis[x][y]=true; d[x][y]=d[xx][yy]+w(x,xx,y,yy); for(R i=0;i<4;++i) { R vx=x+dx[i],vy=y+dy[i]; P s=mkp(vx,vy); if(ckpos(vx,vy)||vis[vx][vy]) continue; if(w(vx,x,vy,y)) q.push_back(mkp(v,s)); else q.push_front(mkp(v,s)); } } } signed main() { t=g(); while(t--) { memset(d,0,sizeof(d)),memset(vis,0,sizeof(vis)); r=g(),c=g(); for(R i=1;i<=r;++i) { scanf("%s",s+1); for(R j=1;j<=c;++j) if(s[j]=='\\') mp[i][j]=1; else mp[i][j]=0; } bfs(); if(vis[r+1][c+1]) printf("%d\n",d[r+1][c+1]); else printf("NO SOLUTION\n"); } }
2019.04.26