HDU 2612 Find a way 題解
Find a way
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 25379 Accepted Submission(s): 8243
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest.
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes.
Each test case include, first two integers n, m. (2<=n,m<=200).
Next n lines, each line included m character.
‘Y’ express yifenfei initial position.
‘M’ express Merceki initial position.
‘#’ forbid road;
‘.’ Road.
‘@’ KCF
1 //Author:LanceYu 2 #include<iostream> 3 #include<string> 4 #include<cstring> 5 #include<cstdio> 6 #include<fstream> 7 #include<iosfwd> 8 #include<sstream> 9 #include<fstream> 10 #include<cwchar> 11 #include<iomanip> 12 #include<ostream> 13 #include<vector> 14 #include<cstdlib> 15 #include<queue> 16 #include<set> 17 #include<ctime> 18 #include<algorithm> 19 #include<complex> 20 #include<cmath> 21 #include<valarray> 22 #include<bitset> 23 #include<iterator> 24 #define ll long long 25 using namespace std; 26 const double clf=1e-8; 27 //const double e=2.718281828; 28 const double PI=3.141592653589793; 29 const int MMAX=2147483647; 30 //priority_queue<int>p; 31 //priority_queue<int,vector<int>,greater<int> >pq; 32 struct node 33 { 34 int x,y,step; 35 }; 36 queue<node> q; 37 int n,k,vis[201][201]; 38 char map[201][201]; 39 int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//四個方向 40 int bfs(int a,int b,int r1,int r2) 41 { 42 while(!q.empty()) 43 q.pop(); 44 int i; 45 q.push(node{a,b,0}); 46 vis[a][b]=1; 47 while(!q.empty()) 48 { 49 node t=q.front(); 50 q.pop(); 51 if(t.x==r1&&t.y==r2) 52 return t.step; 53 for(i=0;i<4;i++) 54 { 55 int dx=t.x+dir[i][0]; 56 int dy=t.y+dir[i][1]; 57 if(dx>=0&&dy>=0&&dx<n&&dy<k&&!vis[dx][dy]&&map[dx][dy]!='#')//正常搜尋 58 { 59 vis[dx][dy]=1; 60 q.push(node{dx,dy,t.step+1}); 61 } 62 } 63 } 64 return MMAX;//如果搜不到就返回一個不能使ans改變的值 65 } 66 int main() 67 { 68 int a1,b1,a2,b2,r1[40001],r2[40001]; 69 while(scanf("%d%d",&n,&k)!=EOF) 70 { 71 int t=0,ans=MMAX,temp=0; 72 for(int i=0;i<n;i++) 73 { 74 scanf("%s",&map[i]); 75 for(int j=0;j<k;j++) 76 { 77 if(map[i][j]=='Y') 78 { 79 a1=i; 80 b1=j; 81 } 82 if(map[i][j]=='M')//求出兩個點的位置作為起點 83 { 84 a2=i; 85 b2=j; 86 } 87 if(map[i][j]=='@')//如果是KFC放到數組裡面 88 { 89 r1[t]=i; 90 r2[t]=j; 91 t++; 92 } 93 } 94 } 95 for(int i=0;i<t;i++)//尋找能到的KFC的最小值 96 { 97 temp=0; 98 memset(vis,0,sizeof(vis)); 99 temp+=bfs(a1,b1,r1[i],r2[i]); 100 memset(vis,0,sizeof(vis)); 101 temp+=bfs(a2,b2,r1[i],r2[i]); 102 ans=min(ans,temp); 103 } 104 printf("%d\n",ans*11); 105 } 106 return 0; 107 }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
乍一看這個程式碼似乎還很有道理
然而
但是為什麼會T呢
原因其實很簡單
就是因為bfs演算法時間複雜度較高
如果多次進行bfs的話
鐵定超時
此處一個KFC就進行一次搜尋
導致超時
於是筆者想出了一個較為不錯的方法
只進行一次bfs
記錄下所能到達的位置所需的步數
這樣只有兩次深搜即可
但是這裡要注意一個小小的bug
就是KFC可能到不了
筆者因為這個WA了幾次的
下面附上我精確註釋
誰都能看懂的程式碼
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 //Author:LanceYu 2 #include<iostream> 3 #include<string> 4 #include<cstring> 5 #include<cstdio> 6 #include<fstream> 7 #include<iosfwd> 8 #include<sstream> 9 #include<fstream> 10 #include<cwchar> 11 #include<iomanip> 12 #include<ostream> 13 #include<vector> 14 #include<cstdlib> 15 #include<queue> 16 #include<set> 17 #include<ctime> 18 #include<algorithm> 19 #include<complex> 20 #include<cmath> 21 #include<valarray> 22 #include<bitset> 23 #include<iterator> 24 #define ll long long 25 using namespace std; 26 const double clf=1e-8; 27 //const double e=2.718281828; 28 const double PI=3.141592653589793; 29 const int MMAX=2147483647; 30 //priority_queue<int>p; 31 //priority_queue<int,vector<int>,greater<int> >pq; 32 struct node 33 { 34 int x,y; 35 }; 36 37 int n,k,vis[201][201]; 38 char map[201][201]; 39 int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//四個方向 40 void bfs(int a,int b,int step[][201])//暴力列舉能到的地方各點的步數 41 { 42 int i; 43 queue<node> q; 44 q.push(node{a,b}); 45 vis[a][b]=1; 46 while(!q.empty()) 47 { 48 node t=q.front(); 49 q.pop(); 50 for(i=0;i<4;i++) 51 { 52 int dx=t.x+dir[i][0]; 53 int dy=t.y+dir[i][1]; 54 if(dx>=0&&dy>=0&&dx<n&&dy<k&&!vis[dx][dy]&&map[dx][dy]!='#'&&!vis[dx][dy])//基本搜尋 55 { 56 vis[dx][dy]=1; 57 step[dx][dy]=step[t.x][t.y]+1; 58 q.push(node{dx,dy}); 59 } 60 } 61 } 62 } 63 int main() 64 { 65 int a1,b1,a2,b2,step1[201][201],step2[201][201]; 66 while(scanf("%d%d",&n,&k)!=EOF) 67 { 68 memset(step1,0,sizeof(step1)); 69 memset(step2,0,sizeof(step2)); 70 int t=0,ans=MMAX; 71 for(int i=0;i<n;i++) 72 { 73 scanf("%s",map[i]); 74 for(int j=0;j<k;j++) 75 { 76 if(map[i][j]=='Y') 77 { 78 a1=i; 79 b1=j; 80 } 81 if(map[i][j]=='M')//把兩個點記錄下來 82 { 83 a2=i; 84 b2=j; 85 } 86 } 87 } 88 memset(vis,0,sizeof(vis)); 89 bfs(a1,b1,step1); 90 memset(vis,0,sizeof(vis)); 91 bfs(a2,b2,step2); 92 for(int i=0;i<n;i++)//遍歷所有元素,使得能走到KFC且為最小 93 { 94 for(int j=0;j<k;j++) 95 { 96 if(map[i][j]=='@'&&step1[i][j]&&step2[i][j]&&(step1[i][j]+step2[i][j]<ans))//注意此處step為0代表KFC到不了 97 ans=step1[i][j]+step2[i][j]; 98 } 99 } 100 printf("%d\n",ans*11); 101 } 102 return 0; 103 }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
此時能夠AC 時間為31ms
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Note:需要注意下bfs的使用次數即可
2018-11-16 00:25:12 Author:LanceYu