diff --git a/content/1_Intro/Running_Code.mdx b/content/1_Intro/Running_Code.mdx index 59993d9..c36ecdd 100644 --- a/content/1_Intro/Running_Code.mdx +++ b/content/1_Intro/Running_Code.mdx @@ -68,16 +68,16 @@ Vim is probably the easiest way to print syntax-highlighted code on Mac, see the - Using `/usr/local/bin/subl` instead of `~/bin/subl` worked for me on OS X Mojave. - [Package - Sublime Linter (GCC)](https://packagecontrol.io/packages/SublimeLinter-gcc) - highlights compilation errors and warnings from `-Wall` +- [Package - Fast Olympic Coding](https://github.com/Jatana/FastOlympicCoding) (I don't use) + - test manager can be useful + - linting is covered by the above + - stress testing is covered in "Debugging" + - can't get debug to work + + - ## On Linux diff --git a/content/3_Bronze/Ad_Hoc.mdx b/content/3_Bronze/Ad_Hoc.mdx deleted file mode 100644 index 90bc7ef..0000000 --- a/content/3_Bronze/Ad_Hoc.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: ad-hoc -title: Approaching Ad Hoc Problems -author: Michael Cao -description: "Tips on Ad Hoc problems (problems with no clear category) in the Bronze Division." -frequency: 2 ---- - -import { Problem } from "../models"; - -export const metadata = { - problems: { - general: [ - new Problem("Bronze", "Cow Tipping", "689", "Hard", false, [], "Cells in the last row and column can be toggled uniquely. Toggle the appropriate ones and then recurse to the rectangle in the previous row/column, and solve the same way."), - new Problem("Bronze", "Race", "989", "Very Hard", false, [], "Greedily increment/decrement Bessies speed to fit the conditions until her total distance exceeds K."), - ], - greedyTutorial: [ - new Problem("Bronze", "Mad Scientist", "1012", "Normal", false, [], ""), - ], - } -}; - -Some bronze problems don't fall into any specific category, such as compete search or rectangle geometry, and often require more thought while also being easier to implement. Any problem that doesn't fall under any well-defined category can be labelled as **Ad Hoc**. - -Since Ad Hoc problems don't fall under any specific category, they can be hard to generalize, so there is no fixed algorithm or idea to solving these problems. In this module, we'll go over some general tips that may be useful in approaching these problems and present some practice problems. - -## Tips for Approaching Ad Hoc Problems - - -These tips are helpful in solving Ad Hoc problems. However, in the end, the best way to get better at Ad Hoc problems (or any type of problems) is to do a lot of them. Try to solve as many practice problems below as you can, and click the solution sketch tab if you can't figure the solution out. - -## Greedy Problems - -One thing to note about Ad Hoc problems in the USACO Bronze division is that many of them, while difficult to categorize into specific algorithms or data structures, can be solved using **Greedy** techniques. While this idea will be covered more in future [modules](https://usaco-guide.netlify.app/silver/greedy), we'll introduce the general mindset in this section. - -When approaching a greedy problem, we want to make argument about the structure of the solution of the problem. Specifically, that certain "greedy" actions, or actions that create the best possible solution at some local point in the algorithm, will lead to an optimal solution at the end. - -Consider some possible greedy algorithms for the USACO Bronze problem "Mad Scientist." - - - - - - In this problem, the correct greedy solution is to continually flip the longest possible ranges of mismatching cows. - - Mad Scientist has an excellent [editorial](http://www.usaco.org/current/data/sol_breedflip_bronze_feb20.html) with a video solution and intuitive proof. - - It is highly recommended you read it to gain a better understanding of the greedy algorithm. - - -However, not all greedy problems in the bronze division necessarily require mathematical proofs of correctness. It is often sufficent to intuitively convince yourself your algorithm is correct. - - -Sometimes, if the algorithm is easy enough to implement, you don't even need to convince yourself it's correct: just let the online judge prove it for you by coding it and seeing if it passes. Competitive programmers refer to this as "Proof by AC," or "Proof by Accepted." - - - - - - - - - - - - - diff --git a/content/3_Bronze/Intro_Greedy.mdx b/content/3_Bronze/Intro_Greedy.mdx new file mode 100644 index 0000000..1643c22 --- /dev/null +++ b/content/3_Bronze/Intro_Greedy.mdx @@ -0,0 +1,175 @@ +--- +id: intro-greedy +title: Introduction to Greedy Algorithms +author: Michael Cao, Darren Yao +description: "Selecting the optimal choice at each step in your algorithm without looking at the solution space as a whole." +frequency: 2 +--- + +import { Problem } from "../models"; + +export const metadata = { + problems: { + tutorial: [ + new Problem("Bronze", "Mad Scientist", "1012", "Normal", false, [], ""), + ], + general: [ + new Problem("Bronze", "Cow Tipping", "689", "Hard", false, [], "Cells in the last row and column can be toggled uniquely. Toggle the appropriate ones and then recurse to the rectangle in the previous row/column, and solve the same way."), + new Problem("Bronze", "Race", "989", "Very Hard", false, [], "Greedily increment/decrement Bessies speed to fit the conditions until her total distance exceeds K."), + ], + } +}; + +## Ad Hoc + +Most bronze problems fall into specific categories, such as simulation and complete search. Those which don't often require more thought, although they are not necessarily more difficult to implement. + +Any problem that doesn't fall under any well-defined category can be labelled as **Ad Hoc**. Since there is no fixed algorithm or idea to solving these problems, they can be hard to generalize. In this module, we'll go over some general tips that may be useful in approaching these problems. + + + +These tips are helpful in solving Ad Hoc problems. However, in the end, the best way to get better at Ad Hoc problems (or any type of problems) is to do a lot of them. Try to solve as many practice problems below as you can, and click the solution sketch tab if you can't figure the solution out. + +## Greedy Algorithms + +Most USACO Bronze problems that appear to be Ad Hoc can actually be solved using **greedy** algorithms. This idea will be covered in a future [module](../silver/greedy), but we'll introduce the general mindset in this section. + + + other examples are outside scope of bronze + + +From the above: + +> A **greedy** algorithm constructs a solution to the problem by always making a +choice that looks the best at the moment. A greedy algorithm never takes back +its choices, but directly constructs the final solution. For this reason, greedy +algorithms are usually very efficient. + +**Greedy** does not refer to a single algorithm, but rather a way of thinking that is applied to problems; there's no one way to do greedy algorithms. Hence, we use a selection of well-known examples to help you understand the greedy paradigm. + +### Example: Studying Algorithms + +Steph wants to improve her knowledge of algorithms over winter break. She has a total of $X$ ($1 \leq X \leq 10^4$) minutes to dedicate to learning algorithms. There are $N$ ($1 \leq N \leq 100$) algorithms, and each one of them requires $a_i$ ($1 \leq a_i \leq 100$) minutes to learn. Find the maximum number of algorithms she can learn. + +#### Solution + + + +The first observation we make is that Steph should prioritize learning algorithms from easiest to hardest; in other words, start with learning the algorithm that requires the least amount of time, and then choose further algorithms in increasing order of time required. Let's look at the following example: + +$$ +X = 15, \qquad N = 6, \qquad a_i = \{ 4, 3, 8, 4, 7, 3 \} +$$ + +After sorting the array, we have $\{ 3, 3, 4, 4, 7, 8 \}$. Within the maximum of 15 minutes, Steph can learn four algorithms in a total of $3+3+4+4 = 14$ minutes. + +The implementation of this algorithm is very simple. We sort the array, and then take as many elements as possible while the sum of times of algorithms chosen so far is less than $X$. Sorting the array takes $O(N \log N)$ time, and iterating through the array takes $O(N)$ time, for a total time complexity of $O(N \log N)$. + + + + + +```cpp +// read in the input, store the algorithms in a vector, algorithms +sort(algorithms.begin(), algorithms.end()); +int count = 0; // number of minutes used so far +int i = 0; +while(count + algorithms[i] <= x){ + // while there is enough time, learn more algorithms + count += algorithms[i]; + i++; +} +cout << i << endl; // print the ans +``` + + + + + +```java +// read in the input, store the algorithms in int[] algorithms +Arrays.sort(algorithms); +int count = 0; // number of minutes used so far +int i = 0; +while(count + algorithms[i] <= x){ + // while there is enough time, learn more algorithms + count += algorithms[i]; + i++; +} +pw.println(i); // print the ans +pw.close(); +``` + + + + + + + +### When Greedy Fails + +We'll provide a few common examples of when greedy fails, so that you can avoid falling into obvious traps and wasting time getting wrong answers in contest. + +#### Coin Change + +This problem gives several coin denominations, and asks for the minimum number of coins needed to make a certain value. Greedy algorithms can be used to solve this problem only in very specific cases (it can be proven that it works for the American as well as the Euro coin systems). However, it doesn't work in the general case. For example, let the coin denominations be $\{1, 3, 4\}$, and say the value we want is 6. The optimal solution is $\{3, 3\}$, which requires only two coins, but the greedy method of taking the highest possible valued coin that fits in the remaining denomination gives the solution $\{4, 1, 1\}$, which is incorrect. + +#### Knapsack + +The knapsack problem gives a number of items, each having a **weight** and a **value**, and we want to choose a subset of these items. We are limited to a certain weight, and we want to maximize the value of the items that we take. + +Let's take the following example, where we have a maximum capacity of 4: + +
+ +| Item | Weight | Value | Value Per Weight | +|------|--------|-------|------------------| +| A | 3 | 18 | 6 | +| B | 2 | 10 | 5 | +| C | 2 | 10 | 5 | + +
+ +If we use greedy based on highest value first, we choose item A and then we are done, as we don't have remaining weight to fit either of the other two. Using greedy based on value per weight again selects item A and then quits. However, the optimal solution is to select items B and C, as they combined have a higher value than item A alone. In fact, there is no working greedy solution. The solution to this problem uses **dynamic programming**, which is covered in gold. + +### Example: Mad Scientist + +Try to come up with a greedy algorithm for the USACO Bronze problem "Mad Scientist." + + + + + +In this problem, the correct greedy solution is to continually flip the longest possible ranges of mismatching cows. + +Mad Scientist has an excellent [editorial](http://www.usaco.org/current/data/sol_breedflip_bronze_feb20.html) with a video solution and intuitive proof. + +It is highly recommended you read it to gain a better understanding of the greedy algorithm. + + + +However, not all greedy problems in the bronze division necessarily require mathematical proofs of correctness. It is often sufficent to intuitively convince yourself your algorithm is correct. + + + +Sometimes, if the algorithm is easy enough to implement, you don't even need to convince yourself it's correct; just code it and see if it passes. Competitive programmers refer to this as "Proof by AC," or "Proof by Accepted." + + + + + +## Problems + + + + + + + + + diff --git a/content/4_Silver/Greedy.mdx b/content/4_Silver/Greedy.mdx index 4918872..188f764 100644 --- a/content/4_Silver/Greedy.mdx +++ b/content/4_Silver/Greedy.mdx @@ -3,9 +3,10 @@ id: greedy title: "Greedy Algorithms" author: Darren Yao prerequisites: + - intro-greedy - sorting-custom - intro-ordered -description: "Greedily selecting the optimal choice at each step in your algorithm instead of looking at the solution space as a whole." +description: "Continuation of greedy problems that were introduced in Bronze." frequency: 3 --- @@ -44,7 +45,7 @@ export const metadata = { }; - Module is based off this. + Module is based off this. @@ -52,74 +53,19 @@ export const metadata = {
-**Greedy** does not refer to a single algorithm, but rather a way of thinking that is applied to problems. There's no one way to do greedy algorithms. Hence, we use a selection of well-known examples to help you understand the greedy paradigm. - -Usually, when using a greedy algorithm, there is a **heuristic** or **value function** that determines which choice is considered most optimal. Here, we'll focus on problems where some sorting step is involved. +Usually, when using a greedy algorithm, there is a **heuristic** or **value function** that determines which choice is considered most optimal. (what's a heuristic or value function?) -## Example: Studying Algorithms +Here, we'll focus on problems where some sorting step is involved. -### Statement - -Steph wants to improve her knowledge of algorithms over winter break. She has a total of $X$ ($1 \leq X \leq 10^4$) minutes to dedicate to learning algorithms. There are $N$ ($1 \leq N \leq 100$) algorithms, and each one of them requires $a_i$ ($1 \leq a_i \leq 100$) minutes to learn. Find the maximum number of algorithms she can learn. - -### Solution - -The first observation we make is that Steph should prioritize learning algorithms from easiest to hardest; in other words, start with learning the algorithm that requires the least amount of time, and then choose further algorithms in increasing order of time required. Let's look at the following example: - -$$X = 15, \qquad N = 6, \qquad a_i = \{ 4, 3, 8, 4, 7, 3 \}$$ - -After sorting the array, we have $\{ 3, 3, 4, 4, 7, 8 \}$. Within the maximum of 15 minutes, Steph can learn four algorithms in a total of $3+3+4+4 = 14$ minutes. -The implementation of this algorithm is very simple. We sort the array, and then take as many elements as possible while the sum of times of algorithms chosen so far is less than $X$. Sorting the array takes $O(N \log N)$ time, and iterating through the array takes $O(N)$ time, for a total time complexity of $O(N \log N)$. - - - - - -```cpp -// read in the input, store the algorithms in a vector, algorithms -sort(algorithms.begin(), algorithms.end()); -int count = 0; // number of minutes used so far -int i = 0; -while(count + algorithms[i] <= x){ - // while there is enough time, learn more algorithms - count += algorithms[i]; - i++; -} -cout << i << endl; // print the ans -``` - - - - - -```java -// read in the input, store the algorithms in int[] algorithms -Arrays.sort(algorithms); -int count = 0; // number of minutes used so far -int i = 0; -while(count + algorithms[i] <= x){ - // while there is enough time, learn more algorithms - count += algorithms[i]; - i++; -} -pw.println(i); // print the ans -pw.close(); -``` - - - - - - -## The Scheduling Problem +## Example: The Scheduling Problem -There are $N$ events, each described by their starting and ending times. Jason would like to attend as many events as possible, but he can only attend one event at a time, and if he chooses to attend an event, he must attend the entire event. Traveling between events is instantaneous. +There are $N$ events, each described by their starting and ending times. You can only attend one event at a time, and if you choose to attend an event, you must attend the entire event. Traveling between events is instantaneous. What's the maximum number of events you can attend? ### Bad Greedy: Earliest Starting Next Event @@ -228,33 +174,6 @@ pw.close(); -## When Greedy Fails - -We'll provide a few common examples of when greedy fails, so that you can avoid falling into obvious traps and wasting time getting wrong answers in contest. - -### Coin Change - -This problem gives several coin denominations, and asks for the minimum number of coins needed to make a certain value. Greedy algorithms can be used to solve this problem only in very specific cases (it can be proven that it works for the American as well as the Euro coin systems). However, it doesn't work in the general case. For example, let the coin denominations be $\{1, 3, 4\}$, and say the value we want is 6. The optimal solution is $\{3, 3\}$, which requires only two coins, but the greedy method of taking the highest possible valued coin that fits in the remaining denomination gives the solution $\{4, 1, 1\}$, which is incorrect. - -### Knapsack - -The knapsack problem gives a number of items, each having a weight and a value, and we want to choose a subset of these items. We are limited to a certain weight, and we want to maximize the value of the items that we take. - -Let's take the following example, where we have a maximum capacity of 4: - -
- -| Item | Weight | Value | Value Per Weight | -|------|--------|-------|------------------| -| A | 3 | 18 | 6 | -| B | 2 | 10 | 5 | -| C | 2 | 10 | 5 | - -
- -If we use greedy based on highest value first, we choose item A and then we are done, as we don't have remaining weight to fit either of the other two. Using greedy based on value per weight again selects item A and then quits. However, the optimal solution is to select items B and C, as they combined have a higher value than item A alone. In fact, there is no working greedy solution. The solution to this problem uses **dynamic programming**, which is covered in gold. - - ## CSES Problems diff --git a/content/ordering.ts b/content/ordering.ts index c20bc3a..7a921de 100644 --- a/content/ordering.ts +++ b/content/ordering.ts @@ -62,7 +62,7 @@ const MODULE_ORDERING: {[key in SectionID]: Category[]} = { "time-comp", "simulation", "rect-geo", - "ad-hoc", + "intro-greedy", ] }, {