Solução Informática Avançado – Semana 64

por

Solução por Lúcio Cardoso

Seja $$dp[i][0]$$ o menor custo para derrubar todos os pilares de $$1$$ a $$i$$ e $$dp[i][1]$$ o menor custo para derrubar todos os pilares de $$1$$ a $$i$$, assumindo que o pilar $$i+1$$ foi derrubado antes do pilar $$i$$.

Assim,

$$dp[i][0] = min(dp[i-1][1] + d[i], dp[i-1][0] + max(0, d[i]-w[i-1]))$$.

Ou seja, analisamos as respostas analisando se o pilar $$i$$ foi derrubado antes ou depois do pilar $$i-1$$.

Além disso,

$$dp[i][1] = min(dp[i-1][1] + max(0, d[i]-w[i+1]), dp[i-1][0] + max(0, d[i]-w[i]-w[i+1]))$$. 

Novamente, analisamos cada um dos casos dentre derrubar $$i$$ antes ou depois de $$i-1$$, sabendo que $$i+1$$ já foi derrubado.

A resposta final do problema será $$dp[N][0]$$, e é fácil perceber que a complexidade final é $$O(n)$$.

 

// Noic – Semana 64 – Avançado
// Complexidade: O(n)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
int d[maxn], w[maxn];
ll dp[maxn][2];
int main(void)
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> d[i] >> w[i];
// casos base
dp[1][0] = d[1], dp[1][1] = max(0, d[1]-w[2]);
for (int i = 2; i <= n; i++)
{
// possibilidades para dp[i][0]
ll b1 = 1LL*d[i] + dp[i-1][1];
ll b2 = dp[i-1][0] + 1LL*max(0, d[i]-w[i-1]);
dp[i][0] = min(b1, b2);
// perceba que se i = n, não há pilar i+1
if (i < n)
{
// possibilidades para dp[i][1]
ll c1 = 1LL*max(0, d[i]-w[i+1]) + dp[i-1][1];
ll c2 = dp[i-1][0] + 1LL*max(0, d[i]-w[i-1]-w[i+1]);
dp[i][1] = min(c1, c2);
}
}
// resposta do problema
cout << dp[n][0] << "\n";
}