Greedy method - black and white connection problem

1. Problem description

black and white connection
Time Limit: 1000 MS Memory Limit: 1000 KB

Description

Given a sequence P[1,2,…,2n] of 2n points on a straight line, each point P[i] is either a white point or a black point, and there are n white points and n black points in total,
The distance between two adjacent points is 1, please design an algorithm to connect each white point with a black point, so that the total length of the connection is the smallest. For example, in the figure there are
4 white dots and 4 black dots are connected in the diagram, and the total length of the connection is 1+1+1+5=8.

Input

Enter m in the first line to indicate that there are m groups of tests. For each group of tests, first enter n (n<=10000), and then enter 2n 0s or 1s, which represent white or
black, where the numbers of 0 and 1 are n respectively.

Output

Output the minimum total connection length for each set of test data.

Sample Input

2
4 
1 1 0 1 0 0 0 1
4
0 0 1 0 1 1 1 0

Sample Output

8
8

 

2. Thinking analysis

The problem is solved using the greedy method:

Idea 1 (relatively simple):
Every time you encounter an unconnected point, look backwards for the first (nearest) different point.
This idea has high time complexity and low space complexity.

Idea 2:
(1) Maintain a black point stack and a white point stack;
(2) Traverse each point in order, if you encounter a white point, check whether the current black point stack is empty, if not empty, the The white point is connected to the black point on the top of the black point stack (because the stack is first-in-first-out, the black point on the top of the stack is the nearest unconnected black point to the white point); when encountering a black point, do a similar operation.
This idea has low time complexity and high space complexity.
 

3. Code example

The logic of idea 1 is relatively simple, so only the code example of idea 2 is given here:

#include <iostream>
#include <stack>
using namespace std;

int main(int argc, const char * argv[]) {
    // 共m组测试数据
    int m;
    cin >> m;
    while((m--) > 0) {
        // 输入黑白点的数量n,即共有2*n个点
        int n;
        cin >> n;
        
        // 创建点数组points并输入各个点
        int* points = new int[2*n];
        for(int pi = 0; pi < 2 * n; ++pi) {
            cin >> points[pi];
        }
        
        // 创建黑白点栈
        stack<int> whitePoints;
        stack<int> blackPoints;
        
        // 初始化结果
        int result = 0;
    
        //依次遍历每一个点
        for(int pi = 0; pi < 2 * n; ++pi) {

            // 如果是白色的点
            if(points[pi] == 0) {
                // 如果黑点栈中没有黑点,就将这个白点入栈。
                if(blackPoints.empty()) {
                    whitePoints.push(pi);
                }
                // 如果黑点栈中有点,则取出栈顶元素,将二者进行配对
                else {
                    result += (pi - blackPoints.top());
                    blackPoints.pop();
                }
            }
            // 如果是黑色的点
            else {
                // 如果白点栈中没有白点,就将这个黑点入栈。
                if(whitePoints.empty()) {
                    blackPoints.push(pi);
                }
                // 如果白点栈中有点,则取出栈顶元素,将二者进行配对
                else {
                    result += (pi - whitePoints.top());
                    whitePoints.pop();
                }
            }
        }
        
        // 输出结果
        cout << result << endl;
        delete [] points;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/lyhizjj/article/details/130626950