1. 程式人生 > >【CH2601】電路維修

【CH2601】電路維修

擴展 一個 題目 hide %s cli pre pri isp

這是一道廣搜題,難點在於對題目的理解和對細節的處理。

對於一個節點,可以向左上、左下、右上、右下四個位置擴展,根據地圖的形態確定每一步擴展的代價。

將代價最小的節點放在隊頭,這樣用雙端隊列來實現。每個節點最多進出隊列一次,所以時間復雜度為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 }
AC Code

【CH2601】電路維修