This is the second problem for Google Code Jam Qualification round 2014, if you are able to solve this problem with the first one(which is very easy) you will be eligible for the next round.
Problem
In this problem, you start with 0 cookies. You gain cookies at a rate of 2 cookies per second, by clicking on a giant cookie. Any time you have at least C cookies, you can buy a cookie farm. Every time you buy a cookie farm, it costs you C cookies and gives you an extra F cookies per second.
Once you have X cookies that you haven’t spent on farms, you win! Figure out how long it will take you to win if you use the best possible strategy.
Example
Suppose C=500.0, F=4.0 and X=2000.0. Here’s how the best possible strategy plays out:
- You start with 0 cookies, but producing 2 cookies per second.
- After 250 seconds, you will have C=500 cookies and can buy a farm that producesF=4 cookies per second.
- After buying the farm, you have 0 cookies, and your total cookie production is 6 cookies per second.
- The next farm will cost 500 cookies, which you can buy after about 83.3333333seconds.
- After buying your second farm, you have 0 cookies, and your total cookie production is 10 cookies per second.
- Another farm will cost 500 cookies, which you can buy after 50 seconds.
- After buying your third farm, you have 0 cookies, and your total cookie production is 14 cookies per second.
- Another farm would cost 500 cookies, but it actually makes sense not to buy it: instead you can just wait until you have X=2000 cookies, which takes about142.8571429 seconds.
Total time: 250 + 83.3333333 + 50 + 142.8571429 = 526.1904762 seconds.
Notice that you get cookies continuously: so 0.1 seconds after the game starts you’ll have 0.2 cookies, and π seconds after the game starts you’ll have 2π cookies.
Input
The first line of the input gives the number of test cases, T. T lines follow. Each line contains three space-separated real-valued numbers: C, F and X, whose meanings are described earlier in the problem statement.
C, F and X will each consist of at least 1 digit followed by 1 decimal point followed by from 1 to 5 digits. There will be no leading zeroes.
Output
For each test case, output one line containing “Case #x: y”, where x is the test case number (starting from 1) and y is the minimum number of seconds it takes before you can have X delicious cookies.
We recommend outputting y to 7 decimal places, but it is not required. y will be considered correct if it is close enough to the correct number: within an absolute or relative error of 10-6. See the FAQ for an explanation of what that means, and what formats of real numbers we accept.
Limits
1 ≤ T ≤ 100.
Small dataset
1 ≤ C ≤ 500.
1 ≤ F ≤ 4.
1 ≤ X ≤ 2000.
Large dataset
1 ≤ C ≤ 10000.
1 ≤ F ≤ 100.
1 ≤ X ≤ 100000.
Sample
Input | Output |
4 30.0 1.0 2.0 30.0 2.0 100.0 30.50000 3.14159 1999.19990 500.0 4.0 2000.0 |
Case #1: 1.0000000 Case #2: 39.1666667 Case #3: 63.9680013 Case #4: 526.1904762 |
Solution:
In this problem every time we have C cookies in our hand we need to decide whether to buy the farm or simply wait for the cookies to grow to X.
Lets assume our current rate is R and we have C cookies with us as of now.
option 1: Don’t buy farm
Now we can get extra (X-C) cookies is time t1 = (X-C)/R;
option 2: Buy farm
If we purchase the farm instead, our rate will increase to R+F while we will loose all cookies, leaving with 0 cookies.
Now we can get X cookies in time t2 = X/(R+F);
if t1 < t2 then the option 1 is best
(X-C)/R < X/(R+F);
(R+F)/R < X/(X-C);
1 + F/R < X/(X-C);
F/R < X/(X-C) -1;
F/R < C/(X-C); R > F*(X-C)/C;
Now at any point of time R = 2 +nF, where n is number of times we purchase a farm
thus 2 + nF > F*(X-C)/C;
n > (F*(X-C)/C – 2)/F;
So we need to purchase the farm till n becomes greater than (F*(X-C)/C – 2)/F, as soon as n becomes greater than (F*(X-C)/C – 2)/F we should go with option 1.
Time taken = C/2 + C/(2 + F) + C /(2 + 2F) —- till C/(2+(n-1)F) + X/(2 + nF);
Here is the solution to Cookie Clicker Alpha problem in Java, this works for both small and large input
package codejam2014; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.Reader; import java.text.DecimalFormat; import java.util.ArrayList; public class CookieClickerAlpha { DecimalFormat df = new DecimalFormat("###.#######"); public String getTime(Double C, Double F, Double X){ Double f = (X - C)/C; f *= F; Double nF = (f -2)/F; int n = (int) Math.ceil(nF); if(n < 0){ n = 0; } //System.out.println("n = "+n); return df.format(getTime(n, C, F, X)); } private Double getTime(int n, Double C, Double F, Double X){ Double time = 0d; Double rate = 2d; for(int i = 0 ; i < n;i++){ time += (C/rate); rate += F; } time += X/rate; return time; } public static void main(String[] argv) { try { long startTime = System.currentTimeMillis(); Reader reader = new FileReader("small.in"); BufferedReader bufReader = new BufferedReader(reader); String x = bufReader.readLine(); int numOfTestCases = Integer.parseInt(x); int count = 0; File file = new File("small.out"); FileWriter writer = new FileWriter(file); for(count =1; count<= numOfTestCases; count++) { ArrayList secondLine = getFloatList(bufReader.readLine()); String output = new CookieClickerAlpha().getTime(secondLine.get(0), secondLine.get(1), secondLine.get(2))+""; writer.write("Case #" + count + ": " + output+"\n"); System.out.println("Case #" + count + ": " + output); } writer.close(); System.out.println("Total time = " + (System.currentTimeMillis() - startTime)); } catch (Exception e) { e.printStackTrace(); } } private static ArrayList getFloatList(String s) { ArrayList intList = new ArrayList(); String[] strArr = s.split(" "); for (String str : strArr) { intList.add(Double.parseDouble(str.trim())); } return intList; } }
Steven Martin says
Here was my PHP solution that works for both small and large inputs in under 5secs.
puzzlersworld says
great may that complex formula is not required then. you just keep on calculating on the fly.
Yves says
In PHP you don’t need the final ‘?>’ at the end 😉