贪心法——区间选点问题

贪心法——区间选点问题

区间选点问题。数轴上有 n 个闭区间 [ai,bi] 。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)。

贪心思想:先按 b 从小到大进行排序,再选择 b0 作为选点 pos ,如果出现 ai>pos ,则以 bi 作为 pos ,再按照这样的方式迭代。直至所有区间遍历完。

区间选点问题算法实现

// 区间数据结构
struct Region {
    // 左区间
    int left;
    // 右区间
    int right;
    operator < (const Region &r) {
        return (right < r.right || (right == r.right && left > r.left));
    }
};


// 贪心法
// 区间选点问题
void region(Region *r, int n) {
    sort(r, r + n);

    int rightR = r[0].right;
    // 记录选点的容器
    vector<int> pos;
    pos.push_back(rightR);

    for(int i = 1; i < n; i++) {
        if(r[i].left > rightR) {
            rightR = r[i].right;
            pos.push_back(rightR);
        }
    }

    cout << "选点为:";
    for(int i = 0; i < pos.size(); i++) {
        cout << pos[i] << " ";
    }
    cout << endl;
    cout << "总选点数为:" << pos.size() << endl << endl;
}

测试主程序

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

// 区间数据结构
struct Region {
    // 左区间
    int left;
    // 右区间
    int right;
    operator < (const Region &r) {
        return (right < r.right || (right == r.right && left > r.left));
    }
};


// 贪心法
// 区间选点问题
void region(Region *r, int n) {
    sort(r, r + n);

    int rightR = r[0].right;
    // 记录选点的容器
    vector<int> pos;
    pos.push_back(rightR);

    for(int i = 1; i < n; i++) {
        if(r[i].left > rightR) {
            rightR = r[i].right;
            pos.push_back(rightR);
        }
    }

    cout << "选点为:";
    for(int i = 0; i < pos.size(); i++) {
        cout << pos[i] << " ";
    }
    cout << endl;
    cout << "总选点数为:" << pos.size() << endl << endl;
}

int main() {
    while(true) {
        // n个开区间
        int n;
        cout << "请输入闭区间的数量(0退出):";
        cin >> n;
        if(!n) {
            break;
        }

        Region r[n];
        for(int i = 0; i < n; i++) {
            cout << "第" << i + 1 << "个闭区间(x,y)为:";
            cin >> r[i].left;
            cin >> r[i].right;
        }

        cout << "最少取点且能满足区间至少一个点的取点方式和总数为:" << endl;
        region(r, n);
    }
    return 0;
}

输出数据

请输入闭区间的数量(0退出):51个闭区间(x,y)为:1 32个闭区间(x,y)为:2 33个闭区间(x,y)为:6 74个闭区间(x,y)为:4 55个闭区间(x,y)为:5 8
最少取点且能满足区间至少一个点的取点方式和总数为:
选点为:3 5 7
总选点数为:3

请输入闭区间的数量(0退出):31个闭区间(x,y)为:1 32个闭区间(x,y)为:5 73个闭区间(x,y)为:8 10
最少取点且能满足区间至少一个点的取点方式和总数为:
选点为:3 7 10
总选点数为:3

请输入闭区间的数量(0退出):31个闭区间(x,y)为:5 72个闭区间(x,y)为:1 63个闭区间(x,y)为:4 8
最少取点且能满足区间至少一个点的取点方式和总数为:
选点为:6
总选点数为:1

请输入闭区间的数量(0退出):0

Process returned 0 (0x0)   execution time : 38.275 s
Press any key to continue.

你可能感兴趣的:(算法,算法竞赛,贪心法,区间选点问题)