USACO Gold 2020 January - Time is Mooney

Authors: Nathan Gong, Ryan Chou, David Guo

Table of Contents

ExplanationImplementation

Official Analysis (C++)

Explanation

We define dp[t][i]\texttt{dp}[t][i] as the maximum moonies Bessie can have at city ii on day tt. Starting with dp[0][0]=0\texttt{dp}[0][0] = 0, we iterate over each day up to TmaxT_{\text{max}}, the maximum number of days, and over each city, updating dp[t+1][j]\texttt{dp}[t + 1][j] for all cities jj reachable from city ii via a directed road.

We compare the current value of dp[t+1][j]\texttt{dp}[t + 1][j] with the value of coming from an adjacent city on the previous day, dp[t][i]+moonies[j]\texttt{dp}[t][i] + \text{moonies}[j], and take the maximum. After processing each day, we calculate the profit as dp[t][0]Ct2\texttt{dp}[t][0] - C \cdot t^2, representing the total moonies minus the travel cost for tt days, and track the maximum profit.

Note that the maximum amount of money Bessie makes is 1000tt21000t - t^2 in the case where she makes 10001000 moonies per city and the cost is 11 mooney. This is also because the edge weights mim_i are bounded by 10001000 moonies. Her earnings become negative when t>1000t > 1000, so we only have to check her movement across the cities for at most 10001000 days.

Implementation

Time Complexity: O(Tmax(N+M))\mathcal{O}(T_{\text{max}} \cdot (N + M))

C++

#include <bits/stdc++.h>
using namespace std;
const int MAX_DAYS = 1000; // Maximum number of days Bessie can travel
int main() {
ifstream read("time.in");
int n, m, c;
read >> n >> m >> c;

Java

import java.io.*;
import java.util.*;
public class Main {
static final int MAX_DAYS = 1000; // Maximum number of days Bessie can travel
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("time.in"));
PrintWriter pw =
new PrintWriter(new BufferedWriter(new FileWriter("time.out")));

Python

with open("time.in", "r") as fin:
n, m, c = map(int, fin.readline().split())
moonies = list(map(int, fin.readline().split()))
adj = [[] for _ in range(n)]
for _ in range(m):
a, b = map(int, fin.readline().split())
adj[a - 1].append(b - 1) # Convert 1-indexed input to 0-indexed
MAX_DAYS = 1000 # Maximum number of days Bessie can travel

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!