Corsa#10152

Corsa (Editoriale)

Sia — la distanza massima che Bessie può percorrere nei primi minuti, a condizione che dopo questi minuti il suo coefficiente di stanchezza sia uguale a .

Prima dell'inizio dell'allenamento sono trascorsi minuti, quindi poniamo dp[0] = 0.

Per calcolare consideriamo due varianti:

  1. Se dopo i primi i - 1 minuti il coefficiente di stanchezza di Bessie è già uguale a , allora essa può semplicemente riposare per un altro minuto:

    dp[i] = dp[i - 1]
  2. Supponiamo che gli ultimi minuti Bessie li abbia trascorsi nel modo seguente:

Dopo questi minuti il coefficiente di stanchezza torna ad essere uguale a . Prima dell'inizio di questo blocco, Bessie ha già trascorso i primi i - 2k minuti dell'allenamento, quindi la distanza massima che poteva percorrere fino a quel momento è uguale a dp[i - 2k].

Durante i primi minuti del blocco Bessie corre e percorre la distanza

d[i − 2k + 1] + d[i − 2k + 2] + ... + d[i - k] = sum[i - k] - sum[i - 2k],

dove

sum[i] = d[1] + d[2] + ... + d[i]

Nei successivi minuti Bessie riposa. Durante il riposo la distanza non aumenta, mentre il coefficiente di stanchezza diminuisce gradualmente fino a .

Così,

dp[i] = \max\left(dp[i-1], \max_{\substack{1 \le k \le m \\ 2k \le i}} \left(dp[i-2k] + sum[i-k] - sum[i-2k]\right)\right)

Implementazione dell'algoritmo

Dichiariamo gli array di lavoro:

#define MAX 10001
int d[MAX], sum[MAX], dp[MAX];

Leggiamo i dati in ingresso.

scanf("%d %d", &n, &m);
for (i = 0; i < n; i++)
  scanf("%d", &d[i]);

Calcoliamo le somme prefisse dell'array .

sum[0] = 0;
for (i = 1; i <= n; i++)
  sum[i] = sum[i - 1] + d[i - 1];

Inizializziamo il valore iniziale .

dp[0] = 0;

Calcoliamo in sequenza i valori dp[1], dp[2], ..., dp[n].

for (i = 1; i <= n; i++)
{

Se al minuto Bessie riposa, allora dp[i] = dp[i - 1].

  dp[i] = dp[i - 1];

Al minuto si conclude un blocco di lunghezza ( minuti di corsa e minuti di riposo). Il coefficiente di stanchezza non può superare . Poiché il blocco stesso deve rientrare in questi minuti, allora 2k \le i.

  for (k = 1; k <= m && 2 * k <= i; k++)
  {

Calcoliamo la distanza runSum, che Bessie ha percorso nei primi minuti dell'ultimo blocco.

    int runSum = sum[i - k] - sum[i - 2 * k];

Per il corrente calcoliamo la distanza ottimale ottenuta e aggiorniamo il valore di .

    int temp = dp[i - 2 * k] + runSum;
    if (temp > dp[i]) dp[i] = temp;
  }
}

Stampiamo la risposta.

printf("%d\n", dp[n]);