【CH2601】电路维修
这是一道广搜题,难点在于对题目的理解和对细节的处理。
对于一个节点,可以向左上、左下、右上、右下四个位置扩展,根据地图的形态确定每一步扩展的代价。
将代价最小的节点放在队头,这样用双端队列来实现。每个节点最多进出队列一次,所以时间复杂度为O(r*c)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 int r,c,dis[510][510],head,tail; 7 char a[510][510]; 8 pair<int,int> q[510*510*2]; 9 bool can(int x,int y) { 10 return x>=0&&x<=r&&y>=0&&y<=c; 11 } 12 void add(int x,int y,int val) { 13 if(dis[x][y]==-1||val<dis[x][y]) { 14 dis[x][y]=val; 15 if(head>tail||val>dis[q[head].first][q[head].second]) q[++tail]=make_pair(x,y); 16 else q[--head]=make_pair(x,y); 17 } 18 } 19 int main() { 20 int t; 21 cin>>t; 22 while(t--) { 23 memset(dis,-1,sizeof(dis)); 24 cin>>r>>c; 25 for(int i=0;i<r;i++) 26 scanf("%s",a[i]); 27 head=tail=505*505; head++; 28 q[++tail]=make_pair(0,0); 29 dis[0][0]=0; 30 while(head<=tail) { 31 int nowx=q[head].first; 32 int nowy=q[head].second; 33 head++; 34 if(can(nowx-1,nowy-1)) { 35 if(a[nowx-1][nowy-1]=='\\') add(nowx-1,nowy-1,dis[nowx][nowy]); 36 else add(nowx-1,nowy-1,dis[nowx][nowy]+1); 37 } 38 if(can(nowx-1,nowy+1)) { 39 if(a[nowx-1][nowy]=='/') add(nowx-1,nowy+1,dis[nowx][nowy]); 40 else add(nowx-1,nowy+1,dis[nowx][nowy]+1); 41 } 42 if(can(nowx+1,nowy-1)) { 43 if(a[nowx][nowy-1]=='/') add(nowx+1,nowy-1,dis[nowx][nowy]); 44 else add(nowx+1,nowy-1,dis[nowx][nowy]+1); 45 } 46 if(can(nowx+1,nowy+1)) { 47 if(a[nowx][nowy]=='\\') add(nowx+1,nowy+1,dis[nowx][nowy]); 48 else add(nowx+1,nowy+1,dis[nowx][nowy]+1); 49 } 50 } 51 if(dis[r][c]==-1) puts("NO SOLUTION"); 52 else printf("%d\n",dis[r][c]); 53 } 54 return 0; 55 }