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