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 }