Skip to content

Commit

Permalink
Merge pull request cpinitiative#573 from SansPapyrus683/master
Browse files Browse the repository at this point in the history
Added solution for Packmen and Magic Ship
  • Loading branch information
dolphingarlic authored Jan 17, 2021
2 parents 4d788f5 fe274f9 commit 389a4bf
Show file tree
Hide file tree
Showing 3 changed files with 581 additions and 13 deletions.
26 changes: 13 additions & 13 deletions content/3_Silver/Binary_Search_Ans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 96,7 @@ export const problems = {
'Normal',
true,
['Binary Search', 'Prefix Sums'],
'binary search on number of the days and then counting full cycles and extra days with prefix sums'
'cf-magship'
),
new Problem(
'CF',
Expand All @@ -123,7 123,7 @@ export const problems = {
'Hard',
false,
[],
'binary search on time and check if packmen can eat all keeping left and right endpoints'
'cf-packmen'
),
new Problem(
'CF',
Expand Down Expand Up @@ -159,7 159,7 @@ export const problems = {
<!-- process numbers from left to right, keep track of the last element of each block and use binary search of lower_bound to find which block the current numbers belongs -->

<Resources>
<Resource source="CF" title="EDU: Binary Search - Step 2" url="https://codeforces.com/edu/course/2/lesson/6/2/practice" starred>
<Resource source="CF" title="EDU: Binary Search - Step 2" url="https://codeforces.com/edu/course/2/lesson/6/2/practice" starred>
</Resource>
<Resource source="IUSACO" title="12 - Binary Search">
module is based off this
Expand Down Expand Up @@ -232,15 232,15 @@ int main() {
// no numbers satisfy the condition
}
```
See [Lambda Expressions](/general/lambda) if you're not familiar with the syntax used in the main function.
See [Lambda Expressions](/general/lambda) if you're not familiar with the syntax used in the main function.

</CPPSection>

<JavaSection>

```java
import java.io.*;
import java.util.*;
import java.io.*;
import java.util.*;

public class test{
public static boolean f(int x){
Expand Down Expand Up @@ -289,7 289,7 @@ def lstTrue(f, lo, hi):
res = lo-1
while lo <= hi:
mid = (lo hi)//2 # find the middle of the current range
if f(mid):
if f(mid):
# if mid works, then all numbers smaller than mid also work
# so we only care about the part after mid
res = mid # update the answer
Expand All @@ -308,7 308,7 @@ print(lstTrue(lambda x:x*x <= 30, 2, 10)) # 5
print(lstTrue(lambda x:False, 2, 10)) # 1
# no numbers satisfy the condition
```
See [Lambda Expressions](https://www.w3schools.com/python/python_lambda.asp) if you're not familiar with the syntax used in the program.
See [Lambda Expressions](https://www.w3schools.com/python/python_lambda.asp) if you're not familiar with the syntax used in the program.

</PySection>

Expand Down Expand Up @@ -365,7 365,7 @@ def lstTrue(f, lo, hi): # python scoping...
return locs["lo"]
```

This code is very cumbersome because we have to use `exec` function to run the code `lo = mid` and `hi = mid - 1`. If you are interested in this function and python scoping rules, please refer to:
This code is very cumbersome because we have to use `exec` function to run the code `lo = mid` and `hi = mid - 1`. If you are interested in this function and python scoping rules, please refer to:

- [Python Scope & the LEGB Rule: Resolving Names in Your Code](https://realpython.com/python-scope-legb-rule)
- [Setting variables with exec inside a function](https://stackoverflow.com/questions/23168282/setting-variables-with-exec-inside-a-function)
Expand Down Expand Up @@ -463,8 463,8 @@ int main() {
<JavaSection>

```java
import java.io.*;
import java.util.*;
import java.io.*;
import java.util.*;

public class test{
public static boolean f(int x){
Expand Down Expand Up @@ -497,8 497,8 @@ def fstTrue(f, lo, hi):
# hi 1 if no x satisfies f
hi =1
while lo < hi:
mid = (lo hi)//2
if f(mid):
mid = (lo hi)//2
if f(mid):
hi = mid
else:
lo = mid 1
Expand Down
266 changes: 266 additions & 0 deletions solutions/CF Magic Ship.mdx
Original file line number Diff line number Diff line change
@@ -0,0 1,266 @@
---
id: cf-magship
source: CF
title: Magic Ship
author: Kevin Sheng
---

[Official Editorial](https://codeforces.com/blog/entry/65365)

<LanguageSection>

<CPPSection>

```cpp
#include <iostream>
#include <vector>
#include <string>
#include <cmath>

using std::cin;
using std::cout;
using std::endl;

bool reachable(std::pair<long long, long long> start,
std::pair<long long, long long> end,
std::string wind,
long long time) {
long long wind_x = 0;
long long wind_y = 0;
for (const char& w : wind) {
switch (w) {
case 'U':
wind_y ;
break;
case 'D':
wind_y--;
break;
case 'L':
wind_x--;
break;
case 'R':
wind_x ;
break;
}
}
// to speed things up, we can skip all the repetitive cycles and just multiply by the total complete amount of cycles
wind_x *= time / wind.length();
wind_y *= time / wind.length();
long long remainder = time % wind.length();
for (long long i = 0; i < remainder; i ) {
switch (wind[i]) {
case 'U':
wind_y ;
break;
case 'D':
wind_y--;
break;
case 'L':
wind_x--;
break;
case 'R':
wind_x ;
break;
}
}
start.first = wind_x;
start.second = wind_y;
return std::abs(start.first - end.first)
std::abs(start.second - end.second) <= time;
}

/**
* https://codeforces.com/problemset/problem/1117/C
* 0 0
* 4 6
* 3
* UUU should output 5
*
* 0 3
* 0 0
* 3
* UDD should output 3
*/
int main() {
std::pair<long long, long long> at_pos; // i'm not taking any chances with integer overflow
cin >> at_pos.first >> at_pos.second;
std::pair<long long, long long> destination;
cin >> destination.first >> destination.second;
long long wind_len;
cin >> wind_len; // won't be using this but oh well
std::string wind_cycle;
cin >> wind_cycle;

long long lo = 0;
long long hi = 20000000000000000; // just spammed a bunch of 0s, it should be long enough
long long valid = -1;
while (lo <= hi) {
long long mid = (lo hi) / 2;
if (reachable(at_pos, destination, wind_cycle, mid)) {
valid = mid;
hi = mid - 1;
} else {
lo = mid 1;
}
}
cout << valid << endl;
}
```
</CPPSection>
<JavaSection>
```java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
/**
* https://codeforces.com/problemset/problem/1117/C
* 0 0
* 4 6
* 3
* UUU should output 5
*
* 0 3
* 0 0
* 3
* UDD should output 3
*/
public class MagicShip {
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
long[] atPos = Arrays.stream(read.readLine().split(" ")).mapToLong(Long::parseLong).toArray();
long[] destination = Arrays.stream(read.readLine().split(" ")).mapToLong(Long::parseLong).toArray();
read.readLine();
char[] winds = read.readLine().toUpperCase().toCharArray();
if (!reachable(atPos, destination, Long.MAX_VALUE / 2, winds)) {
System.out.println(-1);
System.exit(0);
}
long lo = 0;
long hi = Long.MAX_VALUE / 2;
long valid = -1;
while (lo <= hi) {
long mid = lo / 2 hi / 2;
if (reachable(atPos, destination, mid, winds)) {
valid = mid;
hi = mid - 1;
} else {
lo = mid 1;
}
}
System.out.println(valid);
}
private static boolean reachable(long[] from, long[] to, long time, char[] windPattern) {
long windX = 0;
long windY = 0;
// calculate the net change by the wind through one cycle
for (char w : windPattern) {
switch (w) {
case 'U':
windY ;
break;
case 'D':
windY--;
break;
case 'L':
windX--;
break;
case 'R':
windX ;
break;
}
}
// to speed things up, we can multiply the blown amount by the complete cycle amount
windX *= time / windPattern.length;
windY *= time / windPattern.length;
long remainder = time % windPattern.length;
for (int i = 0; i < remainder; i ) { // calculate the remaining wind
switch (windPattern[i]) {
case 'U':
windY ;
break;
case 'D':
windY--;
break;
case 'L':
windX--;
break;
case 'R':
windX ;
break;
}
}
return manhattanDist(new long[] {from[0] windX, from[1] windY}, to) <= time;
}
private static long manhattanDist(long[] from, long[] to) {
return Math.abs(from[0] - to[0]) Math.abs(from[1] - to[1]);
}
}
```

</JavaSection>

<PySection>

```py
"""
0 0
4 6
3
UUU should output 5
0 3
0 0
3
UDD should output 3
"""
from typing import List

def reachable(start: List[int], end: List[int], wind: str, time: int):
start = start.copy()
wind_x = wind.count("R") - wind.count("L") # count the net changes after one wind cycle
wind_y = wind.count("U") - wind.count("D")
cycle_num = time // len(wind)
wind_x *= cycle_num # speed this up by multiplying by the amount of complete cycles in the time
wind_y *= cycle_num

remainder = time % len(wind)
wind = wind[:remainder] # account for the remaining wind
wind_x = wind.count("R") - wind.count("L")
wind_y = wind.count("U") - wind.count("D")

start[0] = wind_x # apply the changes and see if the manhattan distance is less than the time
start[1] = wind_y
return abs(start[0] - end[0]) abs(start[1] - end[1]) <= time


at_pos = [int(i) for i in input().split()]
destination = [int(i) for i in input().split()]
input()
wind_cycle = input()


lo = 0
hi = 2 * 10**14
valid = -1
while lo <= hi:
mid = (lo hi) // 2
if reachable(at_pos, destination, wind_cycle, mid):
valid = mid
hi = mid - 1
else:
lo = mid 1
print(valid)
```

</PySection>

</LanguageSection>
Loading

0 comments on commit 389a4bf

Please sign in to comment.