abc 176 D 、E

D - Wizard in Maze

题意

n*m的迷宫,由 ' . ' 和 ' # '组成,在 ' . ' 位置有两种移动方式:

1. 移动到相邻的 ' . ' 处。

2. 使用一次魔法移动到以当前位置为中心的 5*5范围内的 ' . ' 处。

求从\((C_h,C_w)\)移动到\((D_h,D_w)\)处最少需要使用魔法的次数,如果不可能到达输出-1。

思路

bds+deque,把移动1达到的点放在队列前面,可以将当前位置不需要使用魔法的可以到达的位置走完,把通过移动2达到的点放在队列后面。

代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define mp(x, y) make_pair(x, y)
 5 
 6 const int maxn = 5e5 + 10;
 7 
 8 int nex1[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}, nex2[20][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}, {-2, -2}, {-2, -1}, {-2, 0}, {-2, 1}, {-2, 2}, {-1, 2}, {-1, -2}, {0, 2}, {0, -2}, {1, 2}, {1, -2}, {2, 2}, {2, 1}, {2, 0}, {2, -1}, {2, -2}};
 9 int d[1005][1005];
10 char Map[10005][1005];
11 int n, m;
12 int check(int x, int y)
13 {
14   if (x <= 0 || x > n || y <= 0 || y > m || Map[x][y] == '#')
15     return 0;
16   return 1;
17 }
18 void bfs(int a, int b)
19 {
20   d[a][b] = 0;
21   deque<pair<int, int> > que;
22   que.push_back(mp(a, b));
23   while (!que.empty())
24   {
25     int x, y;
26     x = que.front().first, y = que.front().second;
27     que.pop_front();
28     for (int i = 0; i < 4; i++)
29     {
30       int _x = x + nex1[i][0], _y = y + nex1[i][1];
31       if (check(_x, _y) && d[_x][_y]>d[x][y])
32       {
33         que.push_front(mp(_x, _y));
34         d[_x][_y] = d[x][y];
35       }
36     }
37     for (int i = 0; i < 20; i++)
38     {
39       int _x = x + nex2[i][0], _y = y + nex2[i][1];
40       if (check(_x, _y) && d[_x][_y] > d[x][y]+1)
41       {
42         d[_x][_y] = d[x][y] + 1;
43         que.push_back(mp(_x, _y));
44       }
45     }
46   }
47 }
48 void init()
49 {
50   for (int i = 0; i <= n; i++)
51     for (int j = 0; j <= m; j++)
52       d[i][j] = 1e9;
53 }
54 void solve()
55 {
56   cin>>n>>m;
57   int x, y, tox, toy;
58   cin>>x>>y>>tox>>toy;
59   init();
60   getchar();
61   for (int i = 1; i <= n; i++)
62     scanf("%s", Map[i] + 1);
63   bfs(x, y);
64   if (d[tox][toy] == 1e9)
65     cout << -1 << endl;
66   else
67     cout << d[tox][toy] << endl;
68 }
69 signed main()
70 {
71   solve();
72   return 0;
73 }

E - Bomber

题意

n*m的格子中,有m个目标要摧毁,放置一个炸弹,炸弹会摧毁放置炸弹的行或列中的所有目标,以将炸弹放置在有目标的方形上。求最多能摧毁多少目标。

思路

容易看出答案就是目标最多的行与目标最多的列的和或者和减1,因为\(1\leq n,m\leq 3*10^5\),所以需要一开始就将目标最多的行和列记录下来,然后枚举。不然如果是n*m的复杂度,会导致超时。

代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define pb push_back
 5 
 6 const int maxn = 3e5 + 10;
 7 
 8 int x, y, r[maxn], c[maxn];
 9 vector<int>  rr, cc;
10 set<pair<int,int> >st;
11 void solve()
12 {
13   int h, w, m;
14   cin >> h >> w >> m;
15   int mr = 0, mc = 0;
16   for (int i = 0; i < m; i++)
17   {
18     cin>>x>>y;
19     st.insert(make_pair(x,y));
20     r[x]++;
21     c[y]++;
22     if(mr<r[x])
23       {
24         mr=r[x];
25         rr.clear();
26         rr.pb(x);
27       }
28     else if(mr==r[x])
29     {
30       rr.pb(x);
31     }
32     if(mc<c[y])
33       {
34         mc=c[y];
35         cc.clear();
36         cc.pb(y);
37       }
38     else if(mc==c[y])
39     {
40       cc.pb(y);
41     }
42   }
43   for(int i:rr)
44     for(int j:cc)
45     {
46       if(st.count(make_pair(i,j)))
47         continue;
48       else 
49         {
50           cout<<mr+mc;
51           return;
52         }
53     }
54   cout << mr+mc-1;
55 }
56 signed main()
57 {
58   solve();
59   return 0;
60 }

 

posted @ 2020-08-22 23:26  一个只会爆零的小菜鸡  阅读(301)  评论(0编辑  收藏  举报