Initials: Difference between revisions

From programming_contest
Jump to navigation Jump to search
imported>Kmk21
No edit summary
imported>Kmk21
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 24: Line 24:
The common solution to a problem that almost looks greedy but isn't is to apply some DP to it.
The common solution to a problem that almost looks greedy but isn't is to apply some DP to it.


The state intuitively will include which name we're on, but as the example above shows, it also depends on how many characters we've selected for the PREVIOUS word. This leads to the following recursive relation
The state intuitively will include which name we're on, but as the example above shows, it also depends on how many characters we've added to the word we're on. This leads to the following recursive relation


dp[word][letters added to previous word] = min dp[word + 1][k] where k is some number of letters to add to THIS word to make it sort correctly WRT to previous word with the input number of letters correct.
dp[word][letters added to word] = min dp[word - 1][k]


The value in the dp[i][j] is minimum number of characters to place i and all words after i given that word i-1 has j characters added. Row 0 has special treatment, since there is now word -1, and the minimum will be whatever the value of adding that word 0 is.
The value in the dp[i][j] is minimum number of characters to place i by adding j letters to it.
 
You'll note due to the recursive relation, we have to start at the END of the word list, and the base case is that it takes 0 additions to place the N + 1th word...since there is no n+1th word. Then for each word, from N->1, we iterate over all j (number of letters in previous word), and evaluate the minimum using the above relation.


The DP array has 1000*80 elements, and each relation takes 80 steps, giving us 1k * 80^2, or 6.5 million. Plenty fast.
The DP array has 1000*80 elements, and each relation takes 80 steps, giving us 1k * 80^2, or 6.5 million. Plenty fast.

Latest revision as of 02:39, 18 January 2018

This problem gives us a list of people's names, and rules for forming hashes (take last initial, next k letters of last name, first initial, k-len(last_name)+1) and asks for the minimum k summed over all names such that the hashed names still sort correctly.

The first thing to see is that a greedy solution seems enticing: do the names in order, and add letters until it sorts correctly. This fails, however. Consider just two names (after flipping first and last names, as we have to do)

  • Ma C
  • Mb A

We greedily select MC

  • MC

Then we greedily select MA

  • MC
  • MA

We find however that this sorts incorrectly, so we add a character

  • MC
  • MbA

We find this STILL sorts incorrectly, but are out of letters to add. The only solution is to have taken the 'a' from the first name. Since we need some amount of backtracking, we know the solution cannot be purely greedy.

The common solution to a problem that almost looks greedy but isn't is to apply some DP to it.

The state intuitively will include which name we're on, but as the example above shows, it also depends on how many characters we've added to the word we're on. This leads to the following recursive relation

dp[word][letters added to word] = min dp[word - 1][k]

The value in the dp[i][j] is minimum number of characters to place i by adding j letters to it.

The DP array has 1000*80 elements, and each relation takes 80 steps, giving us 1k * 80^2, or 6.5 million. Plenty fast.