维修电路
两个点,如果有线连接,则边权为0,否则边权为1
如果扩展到一个点,边权是0,则把这个点加入到队列的首端,因为对于权值来说,相当于没扩展
这就是双端队列,这里如果将将要加入的距离与队头的距离比较,会错???
注意不能map[xx][yy]=='\',要map[xx][yy]=='\\'
这个代码是照蓝书抄的,这是一个很巧妙的办法,每个map中的x和y都是要比较的两个x和y中的较小值
而我之前写的把点编号的方法一定会MLE,更不必说直接上四维数组的了
还容易写错
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxm=500007; 6 const int maxn=507; 7 int d[maxn][maxn]; 8 char map[maxn][maxn]; 9 bool vis[maxn][maxn]; 10 pair<int,int>q[maxm*5]; 11 int n,m,head=maxm+1,tail=maxm; 12 bool check(int x,int y){ 13 if(x<0||x>n||y<0||y>m) return false; 14 else return true; 15 } 16 void q_add(int x,int y,int dis,int opt){ 17 if(d[x][y]<0||d[x][y]>dis){ 18 d[x][y]=dis; 19 if(opt==0) q[--head]=make_pair(x,y); 20 else q[++tail]=make_pair(x,y); 21 } 22 } 23 int main(){ 24 int t;cin>>t; 25 while(t--){ 26 memset(d,-1,sizeof(d));d[0][0]=0; 27 memset(vis,false,sizeof(vis)); 28 cin>>n>>m; 29 //if((n+m)%2) {cout<<"NO SOLUTION"<<endl;continue;} 30 for(int i=0;i<n;i++) scanf("%s",map[i]); 31 q[++tail]=make_pair(0,0); 32 while(head<=tail){ 33 int xx=q[head].first;int yy=q[head].second;head++; 34 if(check(xx-1,yy-1)){ 35 if(map[xx-1][yy-1]=='\\') q_add(xx-1,yy-1,d[xx][yy],0); 36 else q_add(xx-1,yy-1,d[xx][yy]+1,1); 37 } 38 if(check(xx-1,yy+1)){ 39 if(map[xx-1][yy]=='/') q_add(xx-1,yy+1,d[xx][yy],0); 40 else q_add(xx-1,yy+1,d[xx][yy]+1,1); 41 } 42 if(check(xx+1,yy-1)){ 43 if(map[xx][yy-1]=='/') q_add(xx+1,yy-1,d[xx][yy],0); 44 else q_add(xx+1,yy-1,d[xx][yy]+1,1); 45 } 46 if(check(xx+1,yy+1)){ 47 if(map[xx][yy]=='\\') q_add(xx+1,yy+1,d[xx][yy],0); 48 else q_add(xx+1,yy+1,d[xx][yy]+1,1); 49 } 50 } 51 if(d[n][m]==-1) cout<<"NO SOLUTION"<<endl; 52 else cout<<d[n][m]<<endl; 53 } 54 return 0; 55 }
如果一开始就判断是错的,要注意也要输入,因为是多组数据,时间复杂度就犯过这个问题