One Point Solution

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Friday, 19 October 2012

SRM 558: Tough

Posted on 06:09 by Unknown

This match seemed a bit harder than usual. The 275 points problem was definitely a more complicated dynamic programming than is usual for the easy slot. It was good though.

Div1 easy: For 275 the one about stamps

There are cells indexed from 0 to n-1. Some (or all) cells have a requirement to be colored red, green or blue. In order to color the cells. First pick a stamp length L, with a cost of stampCost*L. Then paint contiguous group of L cells using that stamp with the same color. Each time you push the stamp, it costs pushCost. You cannot use two or more different colors to paint the same cell. What is the minimum cost? The maximum value of n is 50. The cost values are at most 100000.

Things to consider: First of all, there is always a result. You can always pick L=1. Then the cost is: stampCost + n*pushCost. This also allows us to confirm that the result always fits a 32 bits integer.

Another thing, the maximum useful value of L is 50. With at most 50 possible values of L to try, we can just iterate through each of them, find if it is possible to use that length and then calculate the minimum cost if that stamp length was used. Return the minimum cost you find.

Now let us solve the sub-problem when L is fixed. First add L*stampCost. Let us find the minimum number of pushes. Imagine that we have already decided how to color each of the cells that do not have a color requirement. What is the cost to make that pattern? This all depends on each group of contiguous cells of the same color. For example, to paint RRGGBBBBBRGBRRR, consider each group of contiguous cells of each color: RR, GG, BBBBB, ... etc. What is the minimum number of pushes for each of these groups? Note that when L is greater than the length of one of the groups, this is not possible. Then we imagine L=2 and RRRR, of course, we can just use two pushes. That is len / L. But what if the contiguous length is not a multiple of L? For RRRRR and L=2, you would need to do three stamps, and color one of the cells twice. You will verify that the result in case of len not being a multiple of L is always len/L rounded.

But how can we choose the colors for the cells that can have any color? There might be a way that does not involve dynamic programming. But I can only prove the dynamic programming approach to be correct. Have a function f(p, lastColor, lastLength) that finds the minimum cost of painting cells above index p given that the last color we painted is (lastColor) and the current length of contiguous cells of that color is lastLength. In each step, you can decide one of the three colors. Altering lastColor and lastLength if necessary.

Implementing was not easy as it is not your easiest dp to code. It was also 7:00 AM. I am not that good at 7:00 AM. So I took some long time debugging my solution.

I was lucky though, during the challenge phase I expected there to be failed solutions. I opened the solution of the blue coder that had the most score. And it seemed strange. I think the approach itself might be correct, but it was not doing memoization or anything to avoid recursing too much. It was a time out case. There were large example cases, but I think some of the aspects of this solution were cutting the execution time in those cases. But a string of n * characters was too much. I was very lucky to find a solution that timed out.

Code:

const int INF = numeric_limits<int>::max(); 
struct Stamp
{
string desiredColor;
int pushCost, L;

int dp[51][4][51];

// When iterating through colors we go from 0 to 2, but then we got to
// do some input translation...
int toColorId(char ch)
{
switch(ch) {
case 'R': return 0;
case 'G': return 1;
case 'B': return 2;
}
return 3;
}
// What is the minimum cost to paint a group of length contiguous cells?
int getCost(int length)
{
if ( (length < L) && (length > 0) ) {
return INF;
} else {
return pushCost * ( (length / L) + (length % L != 0) );
}
}
int rec(int p, int last, int lastLength)
{
int &res = dp[p][last][lastLength];
if (res == -1) {
res = INF;

if (p == desiredColor.size()) {
// base case, all cells were painted, calculate the last cost
res = getCost( lastLength );
} else {
// pick one color, that matches desiredColor[p]
// remember the best result we find.
for (int c=0; c<3; c++) {
int r = toColorId(desiredColor[p]);
if ( (r == 3 ) || (r == c)) {
if (c == last) {
//continue this sequence.
res = std::min(res, rec(p+1, c, lastLength + 1) );
} else {
//do the change
int x = rec(p+1, c, 1);
int y = getCost(lastLength);
// careful with overflows.
if ( (x < INF) && (y < INF) && (x < INF - y) ) {
res = std::min(res, x + y);
}
}
}
}
}
}
return res;
}

int getMinimumCost(string desiredColor, int stampCost, int pushCost)
{
// Save some variables:
this->desiredColor = desiredColor;
this->pushCost = pushCost;
int n = desiredColor.size();
// Try each possible value of L. Remember the best result:
int minCost = INF;
for (int L=1; L<=n; L++) {
//reset the dp.
memset(dp, -1, sizeof(dp));
this->L = L;
// call the dp.
int x = rec(0,3,0);
int y = stampCost * L;
if (x < INF) {
minCost = std::min(minCost, x + y );
}

}
return minCost;
}
};

Funny thing, while adding comments to that code, I figured that there is a dp that is a bit easier. You just need a recurrence f(t), the minimum cost to color the first t cells. Then pick a group of the last x contiguous cells. If they are all * or the same color, then call getCost(x) and then recurse to f(t - x).

Div1 550: The one with triangles

A complicated one. O(n^3) should be fine. I think the key is to first pick the pair (P,Q), from there you can calculate (using slopes) the allowed red points. Then you have to count the number of ways to pick red points following a large inequality. I think it is possible. But when I noticed I had nothing and there were only 4 minutes left, I preffered to double check the 275 and try to think of ways to find mistakes in it.

Email ThisBlogThis!Share to XShare to Facebook
Posted in explanation, goodday, srm, topcoder | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • TopCoder SRM 557 - finally
    SRM 557 Explanation for division 1 Easy and match recap. Explanations for div2 easy and div2 medium. It feels like it has been ages since t...
  • SRM 589 Editorial
    I have finished writing the editorial for TopCoder SRM 589: http://apps.topcoder.com/wiki/display/tc/SRM+589 . As you most likely noticed. L...
  • SRM 590 recap and editorial
    Another week another Topcoder match. Not a great day. I had a bad flu and still do. Div1 500: The one with Xor Given a list of cards with nu...
  • SRM 546: relief
    I figured I should post something about this SRM. I've been very busy these weeks because the semester is ending and I tried to win a t-...
  • SRM 526: The killing wait for results
    While I wait for results, here is my perspective on this algorithm contest. It began with issues, it had to be postponed 15 minutes. TC has ...
  • SRM 554 div1 hard: TheBrickTowerHardDivOne
    Link to problem statement We got infinitely many bricks of dimensions 1x1x1 and C different colors. Count the number of towers of size 2x2...
  • SRM 533: Div1 500 MagicBoard explanation
    Finally solved it. It is a nice problem that is worth explaining in a post. You have a grid/board of at most 50x50 cells. Some cells contain...
  • Member SRM 505: Part 1
    So, let me explain a couple of problems from a Topcoder Member SRM that I wrote and never got an editorial. BTW, it was the last member SRM....
  • ListedLinks 2012-02-10
    Saturday Morning Breakfast Cereal comics: Grace Hopper's ghost That Oracle engineer blog post Oracle would really not like anyone to se...
  • Codeforces "Good bye 2013" round
    So it was a special round for coders of both divisions, problems ranged from the super easy problem A to the super difficult problems E,F,G....

Categories

  • acm
  • algorithm
  • answers
  • arenaplugin
  • badday
  • behindthescenes
  • bugs
  • c++
  • censorship
  • codechef
  • codeforces
  • contests
  • crocchamp
  • editorial
  • editorial.srm
  • embarrassing
  • explanation
  • gcj2013
  • gmp
  • goodday
  • google
  • googlecodejam
  • greed
  • groklaw
  • health
  • html
  • httpseverywhere
  • implementation
  • ipsc
  • ispc
  • java
  • kawigiedit
  • kindagoodday
  • lamebook
  • languages
  • lego
  • listedlinks
  • marathon
  • nasa
  • offtopic
  • ouch
  • postmortem
  • postportem
  • practical
  • probably_not_a_good_tip
  • problemsetting
  • programming
  • python
  • quora
  • rant
  • recap
  • slightlygoodday
  • snippet
  • srm
  • stl
  • strategy
  • swerc
  • tco
  • tco12
  • tco13
  • tco2012
  • tco2013
  • ternarysearch
  • topcoder
  • tricks
  • ubuntu
  • uva
  • vjass
  • vkcup
  • wc3
  • zinc

Blog Archive

  • ►  2014 (1)
    • ►  January (1)
  • ►  2013 (141)
    • ►  December (14)
    • ►  November (8)
    • ►  October (13)
    • ►  September (11)
    • ►  August (14)
    • ►  July (15)
    • ►  June (13)
    • ►  May (13)
    • ►  April (12)
    • ►  March (11)
    • ►  February (11)
    • ►  January (6)
  • ▼  2012 (94)
    • ►  December (5)
    • ▼  October (6)
      • SRM 559: Just wow
      • SRM 558: Tough
      • Yesterday's Test SRM
      • TopCoder SRM 557: GreatFairyWar and IncubatorEasy
      • Test SRM the 16th
      • TopCoder SRM 557 - finally
    • ►  September (8)
    • ►  August (6)
    • ►  July (3)
    • ►  June (5)
    • ►  May (8)
    • ►  April (10)
    • ►  March (20)
    • ►  February (16)
    • ►  January (7)
  • ►  2011 (51)
    • ►  December (7)
    • ►  November (12)
    • ►  October (5)
    • ►  September (1)
    • ►  August (3)
    • ►  July (4)
    • ►  June (3)
    • ►  May (7)
    • ►  April (3)
    • ►  March (2)
    • ►  February (1)
    • ►  January (3)
  • ►  2010 (9)
    • ►  December (4)
    • ►  October (1)
    • ►  June (1)
    • ►  May (1)
    • ►  January (2)
  • ►  2009 (1)
    • ►  December (1)
Powered by Blogger.

About Me

Unknown
View my complete profile