One Point Solution

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

Monday, 12 August 2013

SRM 588: ouch (Update)

Posted on 09:45 by Unknown

As I write this, I have to go, I am scheduling this to be up the time the challenge phase ends.

Div1 medium: The one with keys

There are up to 12 rooms, each with some red and green locks (up to 10 of each kind). You can use red or white keys to open red locks and green or white keys to open green locks. Each key is consumed once you use it. Each room has keys inside. What is the maximum number of keys you can have?

I was at first trying to make a viable dynamic programming solution. Similar to a GCJ problem. But I was not able to optimize it.

I eventually settled for a brute force search. Whenever you decide to open a room, you should only use white keys if you NEED to. This approach was slow, so I optimized it using all the dirtiest tricks in the book. Let us see if it passes.

Update: Turns out it passes system tests, so I will explain it.

Try all permutations of the order in which you open the rooms.

If you decide to enter a room and you have enough red and green keys, then you simply shouldn't use white keys. You should always use as little white keys as possible. Turns out this is also the "key" to solve it using dynamic programming.

With this, your approach needs `O(n!)` time, 12! is high, but not very high. So we can try some optimizations.

Imagine that at a given moment, there is one room that can be opened and after opening it, you end up with at least as many keys of each type as before. Then you should always open this room. So you shouldn't try sequences in which this room isn't opened.

Another special case, there is a room that you can open, but after opening it you end up with less keys of each type. This room is never a good idea. Ignore it.

I think that the two previous optimizations are enough , I was about to submit this, but last second I decided I could do an extra optimization, give priority to moves that give the maximum number of total keys, and cut the search when we tried too many options. I am not sure this is necessary, but I put it just in case.. Update 2: Yeah, it turns out this optimization wasn't needed.

Before the match I found out std::function causes a bug in TopCoder. That was too bad, because since there is no sane way to have anonymous recursion in c++ without using it, I had to use an outside function for the backtracking. This meant I had to copy all 5 argument variables as class members. What a bore.


vector<int> doorR,doorG,roomR,roomG,roomW;
int n, best, options[12];

void rec(int p, int r, int g, int w)
{
best = std::max(best, r + g + w);

if (p < n) {
//each tuple is (i, nr,ng,nb):
tuple<int,int,int,int> results[n-p]; //possible options
int t = 0;

for (int i=p; i<n; i++) {
// for each candidate options[i], find if it is possible,
// save it in results
int &x = options[i];
int nr = r - doorR[x];
int ng = g - doorG[x];
int nw = w;
if (nr < 0) {
// Not enough red keys, use white keys
nw += nr;
nr = 0;
}
if (ng < 0) {
// Not enough green keys, use white keys
nw += ng;
ng = 0;
}
if (nw >= 0) {
// if the number of white keys is non-negative we can do it
// Increase the number of keys
nr += roomR[x];
ng += roomG[x];
nw += roomW[x];
if ( nr >= r && ng >= g && nw >= w) {
// This move is always a good idea, we should do it:
swap(options[p], options[i]);
rec(p+1, nr,ng,nw);
t = 0;
swap(options[p], options[i]);
break;
} else if ( nr > r || ng > g || nw > w) {
// Make sure the move is a good idea before adding it
results[t++] = make_tuple(i,nr,ng,nw);
}
}
}
// process tuples:
for (int j=0; j < t; j++) {
int i, nr,ng,nw;
tie(i, nr,ng,nw) = results[j];
swap(options[p], options[i]);
rec(p + 1, nr, ng, nw);
swap(options[i], options[p]);
}
}
}

int maxKeys(vector <int> doorR, vector <int> doorG, vector <int> roomR, vector <int> roomG, vector <int> roomW, vector <int> keys)
{
// copy stuff, this is tedious:
this->n = doorR.size();
this->doorR = doorR;
this->doorG = doorG;
this->roomR = roomR;
this->roomG = roomG;
this->roomW = roomW;
best = 0;
for (int i=0; i<n; i++) {
options[i] = i;
}
rec(0, keys[0], keys[1], keys[2]);
return best;
}

Div1 easy: The one with songs

You have T time available to play as many songs as you can. Each song has a duration and a tone. If the tones of two consecutive songs are `x, y` then you need to rest `abs(x-y)` time units before playing the second song. What is the maximum number of songs?

It took me too long to correctly code this solution. As usual, I waited till there were less than 10 minutes before opening this problem.

The trick is, let us say you decide to play some songs. If the minimum tone is `p` and the maximum tone of the songs you play is `q`, then the minimum time you will need to wait because of the tone is always `q - p`. So, let us pick the minimum and maximum tone of the songs you will play, `O(n^2)` options for this pair. The rest is just to play the best song durations between these tones such that the total duration is less than or equal to `T - q + p`.


int maxSongs(vector <int> duration, vector <int> tone, int T)
{
//sort the tones:
int n = tone.size();
for (int i=0; i<n; i++) {
for (int j=i+1; j<n; j++) {
if (tone[j] < tone[i]) {
swap(tone[j], tone[i]);
swap(duration[j], duration[i]);
}
}
}
int res = 0;
// pick the minimum and maximum tone:
for (int a=0; a < n; a++) {
for (int b=a; b < n; b++) {
int t = T - tone[b] + tone[a];
int c = 0;
// save the durations in a vector
int tim = 0;
vector<int> d;
for (int i=a; i<=b; i++) {
d.push_back(duration[i]);
}
// sort the durations, so that we pick the smallest c durations:
sort(d.begin(), d.end());
for (int x: d) {
if (x <= t) {
t -= x;
c ++;
}
}
// remember the best
res =std::max(res, c);
}
}
return res;
}
Email ThisBlogThis!Share to XShare to Facebook
Posted in badday, explanation, postmortem, 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)
      • Regarding c++ vs. python (in algorithm contests)
      • SRM 589 Editorial
      • SRM 589: Read the statement! (upd)
      • Codeforces #196: slowness
      • SRM 588: ouch (Update)
      • Editorial for SRM 587 is out
      • Test SRM#2 : In which I abuse lambdas
      • ThreeColorabilityEasy (SRM 587 div2 hard)
      • ThreeColorability (SRM 587 div1 hard)
      • SRM 587 editorial previews
      • Test SRM #2 : Revenge of the C++11
      • KawigiEdit 2.3.0
      • SRM 586 Editorial finally there
      • SRM 586 div1 easy and hard editorials
    • ►  July (15)
    • ►  June (13)
    • ►  May (13)
    • ►  April (12)
    • ►  March (11)
    • ►  February (11)
    • ►  January (6)
  • ►  2012 (94)
    • ►  December (5)
    • ►  October (6)
    • ►  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