Skip to content

Commit 5d340b0

Browse files
joi 17-soccer
1 parent 913ff04 commit 5d340b0

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed

JOI/JOI 17-soccer.cpp

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* It's never optimal for someone to touch the ball twice.
3+
*
4+
* We can solve with dijkstra's, where our state is
5+
*
6+
* dist(i, j, k): min cost to get the ball to (i,j) where:
7+
* - if 0 <= k <= 3, k represents the direction the ball is currently traveling
8+
* (the ball is is being kicked)
9+
* - if k = 4, the ball is no longer traveling and is under the posession of a player
10+
*
11+
* We can use multi source BFS to find the min dist between every grid cell and the closest
12+
* player. Then, to transition to k = 4, we can just move the closest player to the
13+
* location of the ball.
14+
*/
15+
16+
#include <bits/stdc++.h>
17+
18+
using namespace std;
19+
20+
using ll = long long;
21+
#define ii pair<int, int>
22+
#define f first
23+
#define s second
24+
#define pb push_back
25+
#define mp make_pair
26+
#define all(x) x.begin(), x.end()
27+
#define sz(x) (int)x.size()
28+
#define F0R(i, n) for (int i = 0; i < n; i++)
29+
#define FOR(i, a, b) for (int i = a; i < b; i++)
30+
#define inf 1000000010
31+
32+
int h, w;
33+
// min dist to get a player to (i, j)
34+
ll getPlayer[501][501];
35+
// min cost to get ball to (i, j)
36+
// {0-3}: direction the ball is currently traveling (kicked)
37+
// 4: The ball has landed and a person is currently holding it
38+
ll dist[501][501][5];
39+
ll a, b, c;
40+
41+
bool g(ii x) {
42+
return x.f >= 0 && x.f <= h && x.s >= 0 && x.s <= w;
43+
}
44+
45+
int main() {
46+
cin.tie(0)->sync_with_stdio(0);
47+
48+
cin >> h >> w;
49+
F0R(i, h+1) F0R(j, w+1) getPlayer[i][j] = 1e18;
50+
F0R(i, h+1) F0R(j, w+1) F0R(k, 5) dist[i][j][k] = 1e18;
51+
cin >> a >> b >> c;
52+
int n; cin >> n;
53+
queue<ii> q;
54+
ii first;
55+
F0R(i, n-1) {
56+
int x, y; cin >> x >> y; q.push(mp(x, y));
57+
if (i == 0) first = mp(x,y);
58+
getPlayer[x][y] = 0;
59+
}
60+
int dx[4]{-1,0,1,0};
61+
int dy[4]{0,-1,0,1};
62+
while (!q.empty()) {
63+
ii u = q.front(); q.pop();
64+
F0R(i, 4) {
65+
ii v = mp(u.f+dx[i], u.s+dy[i]);
66+
if (g(v) && getPlayer[v.f][v.s] == 1e18) {
67+
getPlayer[v.f][v.s] = getPlayer[u.f][u.s]+1;
68+
q.push(v);
69+
}
70+
}
71+
}
72+
ii dest; cin >> dest.f >> dest.s;
73+
74+
priority_queue<pair<ll, pair<ii, int>>, vector<pair<ll, pair<ii, int>>>, greater<pair<ll, pair<ii, int>>>> pq;
75+
pq.push(mp(0, mp(first, 4)));
76+
dist[first.f][first.s][4] = 0;
77+
while (!pq.empty()) {
78+
pair<ll, pair<ii, int>> top = pq.top(); pq.pop();
79+
ll d = top.f;
80+
ii u = top.s.f;
81+
int dir = top.s.s;
82+
if (dist[u.f][u.s][dir] != d) continue;
83+
84+
if (dir == 4) {
85+
// choose a direction and kick it
86+
F0R(i, 4) {
87+
ii v = u;
88+
if (g(v) && dist[v.f][v.s][i] > d+b) {
89+
dist[v.f][v.s][i] = d+b;
90+
pq.push(mp(d+b, mp(v, i)));
91+
}
92+
}
93+
// or, choose a direction and move
94+
F0R(i, 4) {
95+
ii v = mp(u.f+dx[i], u.s+dy[i]);
96+
if (g(v) && dist[v.f][v.s][4] > d+c) {
97+
dist[v.f][v.s][4] = d+c;
98+
pq.push(mp(d+c, mp(v, 4)));
99+
}
100+
}
101+
} else {
102+
// keep kicking it
103+
ii v = mp(u.f+dx[dir], u.s+dy[dir]);
104+
if (g(v) && dist[v.f][v.s][dir] > d+a) {
105+
dist[v.f][v.s][dir] = d+a;
106+
pq.push(mp(d+a, mp(v, dir)));
107+
}
108+
// stop, get somebody to pick it up
109+
if (dist[u.f][u.s][4] > d+getPlayer[u.f][u.s]*c) {
110+
dist[u.f][u.s][4] = d+getPlayer[u.f][u.s]*c;
111+
pq.push(mp(d+getPlayer[u.f][u.s]*c, mp(u, 4)));
112+
}
113+
}
114+
}
115+
116+
ll ans = dist[dest.f][dest.s][4];
117+
F0R(i, 4) ans = min(ans, dist[dest.f][dest.s][i]);
118+
cout << ans << endl;
119+
120+
return 0;
121+
}

input.txt

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1+
300 500
2+
1000000000 1000000000 1000000000
13
2
2-
1 2
4+
0 0
5+
300 500
6+
3 0
7+
3 0
8+
4 0
9+
0 4
10+

0 commit comments

Comments
 (0)