TopCoder StripePainter – SRM 150 Div 1


https://community.topcoder.com/stat?c=problem_statement&pm=1215&rd=4555
Karel is a frustrated painter who works by day in an electrical repair shop. Inspired by the color-coded bands on resistors, he is painting a series of long, narrow canvases with bold colored stripes. However, Karel is lazy and wants to minimize the number of brush strokes it takes to paint each canvas.
Abbreviating each color to a single uppercase letter, Karel would write the stripe pattern red-green-blue-green-red as "RGBGR"(quotes added for clarity). It would take him three brush strokes to paint this pattern. The first stroke would cover the entire canvas in red (RRRRR). The second stroke would leave a band of red on either side and fill in the rest with green (RGGGR). The final brush stroke would fill in the blue stripe in the center (RGBGR).
Given a stripe pattern stripes as a String, calculate the minimum number of brush strokes required to paint that pattern.
 

Definition

    
Class:StripePainter
Method:minStrokes
Parameters:String
Returns:int
Method signature:int minStrokes(String stripes)
(be sure your method is public)
    
 

Notes

-The blank canvas is an ugly color and must not show through.
 

Constraints

-stripes will contain only uppercase letters ('A'-'Z', inclusive).
-stripes will contain between 1 and 50 characters, inclusive.
 

Examples

0)
    
"RGBGR"
Returns: 3
Example from introduction.
1)
    
"RGRG"
Returns: 3
This example cannot be done in two strokes, even though there are only two colors. Suppose you tried to paint both red stripes in one stroke, followed by both green stripes in one stroke. Then the green stroke would cover up the second red stripe. If you tried to paint both green stripes first, followed the red stripes, then the red stroke would cover up the first green stripe.
2)
    
"ABACADA"
Returns: 4
One long stroke in color 'A', followed by one stroke each in colors 'B', 'C', and 'D'.
3)
    
"AABBCCDDCCBBAABBCCDD"
Returns: 7
4)
    
"BECBBDDEEBABDCADEAAEABCACBDBEECDEDEACACCBEDABEDADD"
Returns: 26

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2010, TopCoder, Inc. All rights reserved.

https://blog.csdn.net/makeway123/article/details/45116447
给一个目标字符串,每次可以在空白字符串上将连续的位置刷成某个字符,问最少刷几次变成目标字符串。
如:AAA则是一次,ABA先刷成AAA再刷成ABA需要两次;RGBGRB 需要4次。
字符串长度最多50。
 *  It is not hard to see the state variable can be determined by (1) the start and ending positions
 *  of the stripe ; (2) the color. Since we  will deduce the colors from the input, a state can rely
 *  on just the starting and ending positions only. 
 * 
 *  The key to this questions is the fact that two adjacent chars who share the same color can be
 *  painted in one stroke. 
 *  
 *  The state transition formula is :
 *  Left f(i,j) be the minimum number of strokes to paint S[i..j], then we have 
 *  
 *    f(i,i): obviously it requires one 1 stroke ; // a single character           
 *    f(i,j): we will break the input into two parts, and compute their costs f(i,k) and f(k+1,j) for i<=k<j  
 *            when combining the two costs, we need to consider the following cases:
 *              if S[i] == S[j] then we can save 1 stroke ==> f(i,j) = f(i,k) + f(k+1, j) -1   
 *              if S[k] == S[k+1] then we can also save 1 stroke ==> f(i,j) = f(i,k) + f(k+1,j) -1  
 *            we compare these two cases because they are same-color cases on the boudaries of
 *            two subproblems. 
 *  
 *  Now the difficulty is in the programming: when calculating f(i,j), we need to make sure 
 *  f(i+1,j) and f(i, j-1) are available. From a visual perspective, we are computing a upper
 *  triangluar matrix based on the input string. Initially the diagonal can be easily filled 
 *  with values of 1. 
 *  
 *  ABOUT DP: 
 *    Usually we only use DP and the input to compute a matrix. The key is in the computation
 * rather than in the manipulating the input. So don't need to worry about how to manipulate the 
public int minStrokes(String stripe){
 
int [][]dp=new int[stripe.length()][stripe.length()];
for(int [] d : dp) Arrays.fill(d,1000); 
for(int x=0; x<stripe.length(); x++) dp[x][x]=1;  // basic cases 
 
for(int size=1; size<stripe.length(); size++)
   for(int from=0; from<stripe.length(); from++){
          
     int to=from+size;
     if(to>=stripe.length()) continue;
          
     int min=50;
     for(int k=from; k<to; k++){
         min = Math.min(min, dp[from][k]+dp[k+1][to]);
         
         // NOTE: now we have to subproblems S[from..x] and S[x+1..to]  
         // We need to consider the equlity cases for both ends of subproblems:
         //  i.e. S[from]==S[x], S[from]==[to], S[x] == S[x+1] and S[x+1] == S[to] 
         // 
         // The following statements only considers the equality case between the two subproblems
         // i.e., (1) stripe[from] = stripe[x+1], (2) stripe[x] and stripes[x+1] 
         // It is unnecessary to compare the equality cases inside the two subproblems:
         // i.e., (2) stripe[from] == stripe[x]  and (2) stripe[x+1] and stripe[to] 
         // as these cases will be considered when dealing with those subproblems. 
                   
         if(stripe.charAt(k)==stripe.charAt(k+1)) min=Math.min(min, dp[from][k]+dp[k+1][to]-1);
         if(stripe.charAt(from)==stripe.charAt(to)) min=Math.min(min, dp[from][k]+dp[k+1][to]-1);          
     }
    dp[from][to]=min;
}      
return dp[0][stripe.length()-1];
}
/**
  *  Another implementation using memorisation technique 
  * 
  * @param stripe
  * @return
  */
public int minStrokesM(String stripe){
 
int nChars = stripe.length(); 
    int [][]dp=new int[nChars][nChars];
for(int [] d : dp) Arrays.fill(d,-1); 
for(int x=0; x<stripe.length(); x++) dp[x][x]=1;  // basic cases  
return getValue(stripe, dp, 0, nChars-1); 
}
 
 
 
protected int getValue(String stripe, int[][] dp, int i, int j){
 
if( dp[i][j] != -1 ) return dp[i][j]; 
 
int min = Integer.MAX_VALUE ; 
for(int k=i;  k<j;  k++){
int value = getValue(stripe, dp, i, k) + getValue(stripe, dp, k+1, j); 
min = Math.min(min, value ); 
if( stripe.charAt(i) == stripe.charAt(j)) 
min = Math.min(min, value-1); 
if( stripe.charAt(k) == stripe.charAt(k+1)) 
min = Math.min(min, value-1);  
}
dp[i][j] = min ; 
 
return dp[i][j]; 
}
 
 
 
 
/**
  *  Output the Dynamic Programming's state matrix, for debugging purpose 
  * @param dp
  */
protected static void printStateMatrix(int[][] dp)
{
int nSize = dp.length; 
PrintStream out = System.out ; 
 
out.print(" \t"); 
for(int i=0;   i<nSize;  i++) 
out.print(i +"\t");
out.println(); 
 
for(int i=0;  i<nSize;   i++){
out.print(i + "\t"); 
for(int j=0;  j<nSize; j++)
out.print( dp[i][j] +"\t"); 
out.println(); 
}
out.println(); 
     }

For any given pattern X (where X represents any number of stripes) a new pattern xX (where x is one additional stripe to the left side of X) can be created with just 1 more stroke than the number of strokes neeeded to create X. We'll use this as an upper-bound. So if the pattern X takes 10 strokes, then xX will take at most 11 - possibly less.
The strategy then is to skip the left-most stripe and solve for everything to the right of it. Then determine if the left-most stripe can be added with 0 or 1 additional strokes. For example: GR takes 2 stroke, but R GR also only needs 2 because the left-most and right-most stripes are the same color (You'd paint R first, and then put a G in the middle of it). If the ends weren't the same color, as in B GR, then a third stripe would be needed.
The loop at lines 63-67 divides the substring to the right of the current position into 2 segments. It then tries every possible combination of these segment's lengths. So, if the part to the right was 4 characters long, the first segment would be called with lengths 0, 1, 2, 3, and 4 - while the second segement would have lenghts of 4, 3, 2, 1, and 0. This ensures that each way of dividing up the part to the right is tried.
The solution also uses the notion of memoization. This has been discussed in earlier posts (see HillHike). The idea is that once a particular pattern has been calculated, we'll store it so it never needs to be calculated again. Line 70 stores each combination of start position, string length, and color that gets calculated. Then at line 48, we check to see if the combination has been calculated before. For some tests, it's not possible to finished within the time limit without this technique.
03:     private static final char BLANK_COLOR = 'A' - 1;
04:     private static final int MAX_COLORS = 27;  // A-Z plus one for blank
05: 
06:     /*
07:     * Holds all the combinations of starting position, string size, and color
08:     * that we've encountered before.  If they come up again, we can return
09:     * the stored value and avoid re-calculating.
10:     */
11:     int[][][] alreadySeen;
12: 
13:     public int minStrokes(String stripes) {
14: 
15:         int length = stripes.length();
16: 
17:         /*
18:         * Initialize the alreadySeen array.  The Java spec guarantees all
19:         * values will be set to zero.  No need to do it explicitly.
20:         */
21:         alreadySeen = new int[length][length + 1][MAX_COLORS];
22: 
23:         /*
24:         * Calculate calculateMinStrokes on the entire stripes String, starting
25:         * with a blank canvas.
26:         */
27:         return calculateMinStrokes(stripes, 0, length, BLANK_COLOR);
28:     }
29: 
30:     private int calculateMinStrokes(String stripes, int start, int size,
31:                                     char color) {
32: 
33:         // Breaks the recursive calls.
34:         if (size == 0) return 0;
35: 
36:         /*
37:         * If the left-most color matches the given color, then just move
38:         * on to the next stripe.
39:         */
40:         if (stripes.charAt(start) == color) {
41:             return calculateMinStrokes(stripes, start + 1, size - 1, color);
42:         }
43: 
44:         /*
45:         * If we've already calculated this combination of starting position,
46:         * string length, and colore; then just return that value.
47:         */
48:         if (alreadySeen[start][size][color - BLANK_COLOR] > 0) {
49:             return alreadySeen[start][size][color - BLANK_COLOR];
50:         }
51: 
52:         int min = Integer.MAX_VALUE;
53: 
54:         /*
55:         * Calculates the minimum number of strokes for all possible
56:         * combinations of sub-strings to the right of the current position.
57:         * In the first pass, the first call to calculateMinStrokes will be
58:         * empty, and the entire remainder of the string will be used in the
59:         * second call to calculateMinStrokes.  In each subsequent pass, a
60:         * character is added to the first call, and removed from the second
61:         * call.
62:         */
63:         for (int i = 1; i <= size; i++) {
64:             min = Math.min(min, 1 +
65:                     calculateMinStrokes(stripes, start + 1, i - 1, stripes.charAt(start)) +
66:                     calculateMinStrokes(stripes, start + i, size - i, color));
67:         }
68: 
69:         // Store the calculate value to avoid having to calculate it again.
70:         alreadySeen[start][size][color - BLANK_COLOR] = min;
71: 
72:         return min;
73: 
74:     }




Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts