One Point Solution

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

Thursday, 18 October 2012

Yesterday's Test SRM

Posted on 06:40 by Unknown

It seems clear to me that the admins have a system that can generate random SRM problem sets for unrated SRMs. I wish this could become a system that organizes daily test SRMs at stock schedules. I think that once the idea catches on we could expect around 50 to 100 coders in each "practice SRM".

They would be a bit better than allowing virtual contests in that you still do not know exactly what problems to expect. If you play along and avoid cheating (yourself). They are great practice for real SRMs. Since they will have room assignments of their own, then we can even have a challenge phase. Since I played along and avoided loading old code, yesterday's test SRM felt a lot like a real SRM (with a very bad problem (see bellow), but still)

Div1 Easy: Hotel (SRM 357)

Link to problem statement

KawigiEdit would tell me I already solved this problem and asked me to load a file. I of course said no. It did not matter though, since it was a generic dynamic programming problem so having solved it in the past was not really a big advantage (all of these problems tend to be a blur in your memory of solving problems).

There are n cities (at most 20). For each city i, cost[i] is the cost to get customers[i] from that city. You can get any multiple of cost[i] customers from city i. What is the minimum cost you need to pay to get at least minCustomers customers in total? This means that you do not need to get exactly minCustomers but any value of customers greater than or equal to that. (In fact, it may be possible that it is cheaper to get an amount of customers greater than minCustomers than it is to get exactly minCustomers).

Fear not. Let us name a function f(k, t) that gives the minimum cost to get at least k customers using only the t first cities. (The answer to the real problem is f(minCustomers, n).

For a base case, what happens when t=0? This means that there are no cities from which we can get any customer. A value of k greater than 0 is impossible. (Since we are minimizing, let us put a fake large value as the result - infinity). If k=0, then the minimum cost is 0. In fact, whenever k=0, the minimum cost is 0.

Let us now assume t > 0. Then there is at least one city. Let us take city (t-1). We can decide how many times we get customers from this city. Let us say we choose j for the number of times. Then we will get j * customers[t-1] customers with a cost of j * cost[i]. Then we can make decisions for the remaining cities (decrement t). The necessary number of customers, k is reduced by j * customers[t-1]. Thus the minimum cost (if choosing j) is: f(k - j * customers[t-1], t - 1) + j*cost[t-1]. Note that the new value of k might be negative, in that case we have more customers than needed, but that is really the same as if we had k=0 (We no longer need any more customers). We can just iterate through all the possible values of j and find the minimum cost possible.

That recurrence relation can be memoized or turned into iterative dynamic programming. Like this:

int marketCost(int minCustomers, vector <int> customers, vector <int> cost)
{
const int INF = 10000000;
int n = customers.size();
int dp[1001][21];

for (int t=0; t<=n; t++) {
dp[0][t] = 0;
for (int k=1; k<=minCustomers; k++) {
dp[k][t] = INF;
if (t > 0) { //The base case is when t=0, else we iterate for j
// The valid values of j are 0, 1, ... and up to the first
// value of j that causes k - customers[t-1]*(j-1) to be
// negative or 0
for (int j=0; k - customers[t-1]*(j-1) <= k; j++) {
// If the new k is less than 0, set it to 0.
int nk = std::max(0, c - j*customers[t-1]);
// remember the minimum
dp[k][t] = std::min(dp[k][t], dp[nk][t-1] + j*cost[t-1]);
}
}
}
}
// final result!
return dp[minCustomers][n];
}

Div1 medium: RPGRobot (SRM 201)

Link to statement

Err. I usually try to sum up the problem statement in a quick paragraph. The reason is that Topcoder has the draconic idea to only let registered users read their problem statements. But in this case, I have no choice but to ask people to read that problem statement. It is way too long and complicated for me to reproduce quickly.

I did not solve this problem before. That is not an issue though, because this problem was more about implementation and parsing the problem statement and the input.

I actually found hilarious and funny that old timmey problem writers thought that defining a grammar was clearer than explaining the input. Or that a problem that needed these explanations was a good idea.

Anyway... Since the coordiantes that we can return are at most 24x24 = 576. And the number of moves is at most 16 (Try it). Then we can use simple simulation. For each of the coordinates inside the map, simulate all the moves and verify that the story checks out. For each position, get the list of allowed directions, and compare it with the provided list of allowed directions. Any inconsistency means the starting position was not valid.

But what will happen to you after implementing that idea, is that you will fail many of the 9001 example cases. What is going on? You probably missed a couple of traps from the statement.

First of all, the robot can actually go outside of the map. That is no big deal. Except that the walls outside the map are unknown - They could be anything we need them to be. In effect, when a wall position is outside the map, then it can be counted as a wall if the list of directions provided by the robot says so and also the opposite, if the list of directions provided says there is no wall, we can consider there not to be a wall either.

Many ways to deal with this little issue. The best approach is to simply ignore a direction if the direction's wall position is outside the map. Also note that the problem statement clarifies that the moves will be self-consistent. That is very important, because that means that we do not need to do any extra work outside the map, just simulate the movement.

Many implementation issues regarding how to simulate the movement around the map. Use your usual array of direction vectors, but check against (x + dx[i], y + dy[i]) for the walls but move to (x + 2*dx[i], y + 2*dy[i]) for the position. You will need to know how to parse stuff in your language too...

struct RPGRobot
{
// We will encode each entry of the movements string in this string.
// Note that the first "move" is really only the info of allowed directions.
struct move
{
char movedTo;
string allowed;
};
vector<move> moves;

// Returns the state of the wall at a given position.
// If the wall is outside the map, the status is unknown: '?'.
// If there is no wall, the direction is allowed: 'Y'
// Else we cannot move: 'N'.
char couldIt(const vector<string> map, int x, int y) {
if ( x >= map[0].size() || y >= map.size() || x < 0 || y < 0) {
return '?';
} else {
return ( (map[y][x] == ' ') ? 'Y' : 'N' );
}
}

bool sim(vector<string> & map, int x, int y)
{
/* The simulation... */
// Direction vectors
const int dx[4] = {0,0,-1,1};
const int dy[4] = {-1,1,0,0};
// name each direction...
const char* dn = "NSWE";

// Remember what each direction name means...
int did[256];
for (int i=0; i<4; i++) {
did[dn[i]] = i;
}

for (int i=0; i<moves.size(); i++) {
if (i != 0) { // perform move (No move is performed in the first entry)
int d = did[ moves[i].movedTo];

// move two coordinates towards that direction
x += dx[d] * 2;
y += dy[d] * 2;
}
// Check if the allowed directions from this position are consistent
// with the input provided:
for (int d=0; d<4; d++) {
// the wall is only one coordinate towards the direction
int nx = x + dx[d];
int ny = y + dy[d];
// couldIt returns the state of the wall, right?
char c = (couldIt(map, nx, ny));
if (c != '?') { //ignore if the state of the wall is unknown
// should this direction be allowed? Or not?
bool should = false;
for (int k=0; k<moves[i].allowed.size(); k++) {
should |= (moves[i].allowed[k] == dn[d]);
}
// Consistent?
if ( should != (c=='Y') ) {
return false;
}
}
}
}
return true;
}

// Turn that movements string into a vector of structs...
void parseMoves(string& movements)
{
// No easy way to split by commas in c++, we will have to do it manually
int last = 0;
for (int i=0; i <= movements.size(); i++) {
if ( (i==movements.size()) || (movements[i] == ',') ) {
string x = movements.substr(last, i - last);
move tm;
if (last == 0) {
tm.movedTo = '-';
tm.allowed = x;
} else {
// istringstream is good at spliting by spaces.
istringstream st( x) ;
st >> tm.movedTo >> tm.allowed;
}
moves.push_back(tm);
last = i+1;
}
}
}


};

Div1 Hard: RadarGuns (SRM 372)

I remembered this problem too well. I skipped it. It was the problem in which I first tried to do min-cost matching. There are issues with the practice rooms, so I will not say anything else.

Actually, we have editorials for these problems, you know.

The random number gods were evil this time, because the combination of the super implementation medium plus the hard that can be solved by pasting min-cost-flow code is not a great one.

Email ThisBlogThis!Share to XShare to Facebook
Posted in explanation, 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