Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Because you may throw fireballs at already-dead archers, the order of spells is irrelevant. Try thinking in terms of counts : how many times do you shoot each internal position?
Process the line from left to right. When you are deciding shots at position , that is the last chance to damage archer .
After choosing shots on positions to , archers to must already be dead, and archer is still untouched. So the whole prefix can be summarized by just two numbers: the remaining health of archers and .
Let the state be where and are the remaining health of archers and . If you shoot position exactly times, you must have (strictly <0, not <=0), then the next state becomes .
Now memoize and try all from to . The bound is enough because every health is at most , so neighbor hits already deal more than enough damage. Base case: at , choose the smallest that kills archers , , and , and store choices to reconstruct the answer.
Let be how many times we shoot archer for from to .
Because damage is additive and the statement explicitly allows shooting dead archers, only the counts matter. The sequence order does not. For an internal archer the total damage is
For the edges, only one neighbor term exists.
We need every archer to end with health <0, not <=0. Yes, the game is that petty.
A brute force over all vectors is still ugly: each can be up to , so this is about . Too much.
Suppose we are about to decide how many times to shoot position .
All shots on positions to are already fixed.
Now look at who can still change:
So the entire useful state is just the remaining health of archers and .
That is the whole damn trick.
Define
as the minimum number of additional shots needed on positions to if:
Any negative health is equivalent, so we clip every negative value to :
Since every initial health is at most , the only possible stored values are .
Assume and we fire times at position .
First, archer must die now, because after this step nobody can touch it anymore. So we require
After those shots:
So the next state is
Hence
The minimum is taken over all integers from to such that .
Why is enough? Because and :
So shots at one position already kill every archer that position can affect. More than that is pure waste.
At we are deciding the last shootable position. It affects exactly archers , , and .
So we just need the smallest such that
Equivalently,
where if , otherwise .
Induction on .
At state , every valid solution must choose some number of shots at position . That choice is valid iff it kills archer now, meaning . After choosing , the future no longer cares about anything on the far left; it only needs the remaining health of archers and , which is exactly the next state we compute. So the recurrence checks every possible valid first move and picks the best one.
The base case is obviously correct because only one shootable position remains.
Done. No black magic, just a tiny profile DP.
Store which value of gave the best answer for each state. Start from the initial state
Follow the stored choices, and print index exactly times.
Since order does not matter, printing them grouped by position is completely valid.
Number of states:
Each state tries at most values of .
So the total complexity is
with memory
That is tiny. The reduced constraints basically hand you this DP on a silver platter.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int INF = (int)1e9;
int n, a, b;
vector<int> h;
int memo[11][17][17];
int takeShot[11][17][17];
int cliphp(int x) {
return x < 0 ? -1 : x;
}
// Minimum x such that hp - dmg * x < 0.
int need(int hp, int dmg) {
if (hp < 0) return 0;
return hp / dmg + 1;
}
// We are about to choose how many times to shoot position i.
// Archers 1..i-2 are already dead.
// Archer i-1 has remaining hp u, archer i has remaining hp v.
int solve(int i, int u, int v) {
int &res = memo[i][u + 1][v + 1];
if (res != -1) return res;
int &pick = takeShot[i][u + 1][v + 1];
if (i == n - 1) {
pick = max({need(u, b), need(v, a), need(h[n], b)});
return res = pick;
}
res = INF;
pick = 0;
for (int x = need(u, b); x <= 16; ++x) {
int nu = cliphp(v - a * x);
int nv = cliphp(h[i + 1] - b * x);
int cur = x + solve(i + 1, nu, nv);
if (cur < res) {
res = cur;
pick = x;
}
}
return res;
}
int main() {
setIO();
cin >> n >> a >> b;
h.assign(n + 1, 0);
for (int i = 1; i <= n; ++i) cin >> h[i];
memset(memo, -1, sizeof(memo));
int best = solve(2, h[1], h[2]);
vector<int> ans;
ans.reserve(best);
int i = 2, u = h[1], v = h[2];
while (true) {
int x = takeShot[i][u + 1][v + 1];
for (int t = 0; t < x; ++t) ans.push_back(i);
if (i == n - 1) break;
int nu = cliphp(v - a * x);
int nv = cliphp(h[i + 1] - b * x);
u = nu;
v = nv;
++i;
}
cout << best << '\n';
for (int x : ans) cout << x << ' ';
cout << '\n';
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int INF = (int)1e9;
int n, a, b;
vector<int> h;
int memo[11][17][17];
int takeShot[11][17][17];
int cliphp(int x) {
return x < 0 ? -1 : x;
}
// Minimum x such that hp - dmg * x < 0.
int need(int hp, int dmg) {
if (hp < 0) return 0;
return hp / dmg + 1;
}
// We are about to choose how many times to shoot position i.
// Archers 1..i-2 are already dead.
// Archer i-1 has remaining hp u, archer i has remaining hp v.
int solve(int i, int u, int v) {
int &res = memo[i][u + 1][v + 1];
if (res != -1) return res;
int &pick = takeShot[i][u + 1][v + 1];
if (i == n - 1) {
pick = max({need(u, b), need(v, a), need(h[n], b)});
return res = pick;
}
res = INF;
pick = 0;
for (int x = need(u, b); x <= 16; ++x) {
int nu = cliphp(v - a * x);
int nv = cliphp(h[i + 1] - b * x);
int cur = x + solve(i + 1, nu, nv);
if (cur < res) {
res = cur;
pick = x;
}
}
return res;
}
int main() {
setIO();
cin >> n >> a >> b;
h.assign(n + 1, 0);
for (int i = 1; i <= n; ++i) cin >> h[i];
memset(memo, -1, sizeof(memo));
int best = solve(2, h[1], h[2]);
vector<int> ans;
ans.reserve(best);
int i = 2, u = h[1], v = h[2];
while (true) {
int x = takeShot[i][u + 1][v + 1];
for (int t = 0; t < x; ++t) ans.push_back(i);
if (i == n - 1) break;
int nu = cliphp(v - a * x);
int nv = cliphp(h[i + 1] - b * x);
u = nu;
v = nv;
++i;
}
cout << best << '\n';
for (int x : ans) cout << x << ' ';
cout << '\n';
}