This repository has been archived on 2022-06-22. You can view files and clone it, but cannot push or open issues or pull requests.
usaco-guide/content/3_Bronze/Simulation.mdx
2020-07-06 21:31:06 -04:00

161 lines
7.1 KiB
Text

---
id: simulation
title: "Simulation"
author: Darren Yao
description: "In many problems, we can just simulate what we're told to do by the problem statement."
frequency: 4
---
import { Problem } from "../models"
export const metadata = {
problems: {
easier: [
new Problem("Bronze", "Shell Game", "891", "Easy", false, ["Nested Loop"]), // 99.93
new Problem("Bronze", "Mixing Milk", "855", "Easy", false, ["Single Loop"], "just pour 100 times"), // 99.87
new Problem("Bronze", "Speeding", "568", "Easy", false, ["Nested Loop"], "store speed for each mile"), // 99.05
new Problem("Bronze", "The Lost Cow", "735", "Easy", false, ["Single Loop"], ""), // 99.46
new Problem("Bronze", "The Bovine Shuffle", "760", "Easy", false, []), // 100
],
harder: [
new Problem("Bronze", "Circular Barn", "616", "Normal", false, []), // 99.25
new Problem("Bronze", "Block Game", "664", "Normal"), // 97.41
new Problem("Bronze", "Team Tic Tac Toe", "831", "Normal"), // 97.41
new Problem("Bronze", "Cow Queue", "713", "Normal", false, []), // 97.59
new Problem("Bronze", "Mowing the Field", "593", "Normal", false, []), // 97.16
new Problem("Bronze", "Milk Measurement", "761", "Hard"), // 95.97
new Problem("Bronze", "Angry Cows", "592", "Hard", false, [], ""), // 94.15
]
}
};
Since there's no formal algorithm involved, the intent of the problem is to assess competence with one's programming language of choice and knowledge of built-in data structures. At least in USACO Bronze, when a problem statement says to find the end result of some process, or to find when something occurs, it's usually sufficient to simulate the process naively.
## Example 1
### Statement
Alice and Bob are standing on a 2D plane. Alice starts at the point $(0, 0)$, and Bob starts at the point $(R, S)$ ($1 \leq R, S \leq 1000$). Every second, Alice moves $M$ units to the right, and $N$ units up. Every second, Bob moves $P$ units to the left, and $Q$ units down. ($1 \leq M, N, P, Q \leq 10$). Determine if Alice and Bob will ever meet (be at the same point at the same time), and if so, when.
#### Input Format
The first line of the input contains $R$ and $S$.
The second line of the input contains $M$, $N$, $P$, and $Q$.
#### Output Format
Please output a single integer containing the number of seconds after the start at which Alice and Bob meet. If they never meet, please output $-1$.
<spoiler title="Solution">
We can simulate the process. After inputting the values of $R$, $S$, $M$, $N$, $P$, and $Q$, we can keep track of Alice's and Bob's $x$- and $y$-coordinates. To start, we initialize variables for their respective positions. Alice's coordinates are initially $(0, 0)$, and Bob's coordinates are $(R, S)$ respectively. Every second, we increase Alice's $x$-coordinate by $M$ and her $y$-coordinate by $N$, and decrease Bob's $x$-coordinate by $P$ and his $y$-coordinate by $Q$.
Now, when do we stop? First, if Alice and Bob ever have the same coordinates, then we are done. Also, since Alice strictly moves up and to the right and Bob strictly moves down and to the left, if Alice's $x$- or $y$-coordinates are ever greater than Bob's, then it is impossible for them to meet.
Example code is displayed below. Here, as in other examples, input processing will be omitted.
```cpp
int ax = 0; int ay = 0; // alice's x and y coordinates
int bx = r; int by = s; // bob's x and y coordinates
int t = 0; // keep track of the current time
while(ax < bx && ay < by){
// every second, update alice's and bob's coordinates and the time
ax += m; ay += n;
bx -= p; by -= q;
t++;
}
if(ax == bx && ay == by){ // if they are in the same location
cout << t << endl; // they meet at time t
} else {
cout << -1 << endl; // they never meet
}
```
```java
int ax = 0; int ay = 0; // alice's x and y coordinates
int bx = r; int by = s; // bob's x and y coordinates
int t = 0; // keep track of the current time
while(ax < bx && ay < by){
// every second, update alice's and bob's coordinates and the time
ax += m; ay += n;
bx -= p; by -= q;
t++;
}
if(ax == bx && ay == by){ // if they are in the same location
out.println(t); // they meet at time t
} else {
out.println(-1); // they never meet
}
out.close(); // flush the output
```
</spoiler>
## Example 2
### Statement
There are $N$ buckets ($5 \leq N \leq 10^5$), each with a certain capacity $C_i$ ($1 \leq C_i \leq 100$). One day, after a rainstorm, each bucket is filled with $A_i$ units of water ($1\leq A_i \leq C_i$). Charlie then performs the following process: he pours bucket $1$ into bucket $2$, then bucket $2$ into bucket $3$, and so on, up until pouring bucket $N-1$ into bucket $N$. When Charlie pours bucket $B$ into bucket $B+1$, he pours as much as possible until bucket $B$ is empty or bucket $B+1$ is full. Find out how much water is in each bucket once Charlie is done pouring.
#### Input Format
The first line of the input contains $N$.
The second line of the input contains the capacities of the buckets, $C_1, C_2, \dots, C_N$.
The third line of the input contains the amount of water in each bucket $A_1, A_2, \dots, A_N$.
#### Output Format
Please print one line of output, containing $N$ space-separated integers: the final amount of water in each bucket once Charlie is done pouring.
<spoiler title="Solution">
Once again, we can simulate the process of pouring one bucket into the next. The amount of milk poured from bucket $B$ to bucket $B+1$ is the smaller of the amount of water in bucket $B$ (after all previous operations have been completed) and the remaining space in bucket $B+1$, which is $C_{B+1} - A_{B+1}$. We can just handle all of these operations in order, using an array $C$ to store the maximum capacities of each bucket, and an array $A$ to store the current water level in each bucket, which we update during the process. Example code is below (note that arrays are zero-indexed, so the indices of our buckets go from $0$ to $N-1$ rather than from $1$ to $N$).
```cpp
for(int i = 0; i < n-1; i++){
int amt = min(A[i], C[i+1]-A[i+1]);
// the amount of water to be poured is the lesser of
// the amount of water in the current bucket and
// the amount of additional water that the next bucket can hold
A[i] -= amt; // remove the amount from the current bucket
A[i+1] += amt; // add it to the next bucket
}
for(int i = 0; i < n; i++){
cout << A[i] << " ";
// print the amount of water in each bucket at the end
}
cout << endl;
```
```java
for(int i = 0; i < n-1; i++){
int amt = Math.min(A[i], C[i+1]-A[i+1]);
// the amount of water to be poured is the lesser of
// the amount of water in the current bucket and
// the amount of additional water that the next bucket can hold
A[i] -= amt; // remove the amount from the current bucket
A[i+1] += amt; // add it to the next bucket
}
for(int i = 0; i < n; i++){
pw.print(A[i] + " ");
// print the amount of water in each bucket at the end
}
pw.println(); // print newline
pw.close(); // flush the output
```
</spoiler>
## Problems
### Easier
<problems-list problems={metadata.problems.easier} />
### Harder
<problems-list problems={metadata.problems.harder} />