USACO Section 1.1 Broken Necklace

来源:互联网 发布:书包推荐 知乎 编辑:程序博客网 时间:2024/06/06 01:16

Problem statement:

See USACO


My analysis and solution:

Most of the solutions provided on the web use DP to solve this problem. The time cost is O(n). However, the additional space cost is also O(n). By using a queue, the additional space can be down to O(1).

Let's take a close look at a sample input: wwwbbrwrbrbrrbrbrwrwwrbwrwrrb. We can cut them into different block, so that beads in every block have same color: www.bb.r.w.r.b.r.b.rr.b.r.b.r.w.r.ww.r.b.w.r.w.rr.b. And notice that, if the two neighbors of a white block have the same color (for example, blue), these three blocks can be merged together to form one block (with color blue).

Starting from the beginning of the input, we scan the necklace to find a new block while maintaining a block queue.

typedef struct{    char color;  //color of the block.    int num; //the number of beads in this block.    int start: //record the start point of this block.}BLOCK;

The operations of this queue include:

1. Enqueue.

2. Dequeue.

3. Merge blocks.

The algorithm works as follows:

//peudocode://Use an array to implement the queueBLOCK_QUEUE block_queue;int i_longest_length = 0; //Record the longest length found so farint i_current_sum = 0; //Record the sum of all beads number in the block queueBLOCK block;while(block=FindANewBlock()){if (block_queue.size<=2){block_queue.enqueue(block);i_current_sum += block.num;i_longest_length = max(i_longest_length, i_current_sum);}else if (block.color=='w'){block_queue.enqueue(block);i_current_sum += block.num;i_longest_length = max(i_longest_length, i_current_sum);}else if (block_queue.block[block_queue.size-1].color=='w'&&block_queue.block[block_queue.size-2].color==block.color){//if the tail'color is white and the block ahead of the tail and the new block have the same color//queue: w-b-r-w//new block: rMergeBlock(block_queue.block[block_queue.size-1], block_queue.block[block_queue.size-2]);MergeBlock(block_queue.block[block_queue.size-1], block);i_current_sum += block.num;i_longest_length = max(i_longest_length, i_current_sum);}else if (block_queue.block[0].color==block.color){//queue: b-w-r-w//new block: bi_current_sum += (block.num - block_queue.block[0].num);block_queue.dequeue();block_queue.enqueue(block);i_longest_length = max(i_longest_length, i_current_sum);}else if (block_queue.block[1].color==block.color){//queue: w-b-w-r-w//new block: bi_current_sum += (block.num - block_queue.block[0].num - block_queue.block[1].num);block_queue.dequeue();block_queue.dequeue();block_queue.enqueue(block);i_longest_length = max(i_longest_length, i_current_sum);}}

And this is not done yet, because the necklace is a loop! However, it can be easily done by carefully treat the boundary condition and do the while procedure again. In the second while loop, we could add a condition: the new block's start point must less the the start point of the head of the queue.
The length (or size) of the queue is at most 5. For example, w-b-w-r-w. So the additional space requirement is O(1).