大意:数轴上有n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定的线段[s,t]。

 

思路:贪心,具体见刘汝佳白书P154。把各区间按照a从小到大排序。如果区间1的起点不是s,无解,否则选择起点在s的最长区间。选择此区间[ai,bi]后,新的起点设置为bi,然后经过依次扫描之后就可以得出最小的线段数。并用另一个结构体储存路径。

 

另外:排序可有可无,有了只不过是一种优化措施,没有排序的话程序也对,最主要的算法还是贪心。

 

CODE:

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

#define MAXN 100010

struct node
{
    int l;
    int r;
}a[MAXN] , path[MAXN];

int cmp(const node &a, const node &b)
{
    if(a.l != b.l)    return a.l < b.l;
    else return a.r > b.r;    //这里不影响程序的正确性 
}

int n, m;

void init()
{
    memset(a, 0sizeof(a));
    memset(path, 0sizeof(path));
}

void solve()
{
    int flag, pos;
    int Max = 0, tot = 0, ans = 0, left = 0;
    sort(a, a+n, cmp); //排序, 
    for(;;)
    {
        if(left >= m) break;
        Max = flag = 0;
        for(int i = 0; i < n; i++)
        {
            if(a[i].l <= left)
            {
                if(a[i].r > Max)
                {
                    pos = i;
                    Max = a[i].r;
                    flag = 1;
                } //找最右边的区间 
            }
        }
        if(flag)
        {
            ans++;
            left = Max;     //更新最大区间 
            path[tot++] = a[pos];
        }
        else break;
    }
    if(flag)
    {
        printf("%d\n", tot);
        for(int i = 0; i < tot; i++)
        {
            printf("%d %d\n", path[i].l, path[i].r);
        }
    }
    else printf("0\n");
}


int main()
{
    int T;
    scanf("%d%*c", &T);
    while(T--)
    {
        init();
        int i = 0;
        int x, y;
        scanf("%d", &m);
        while(scanf("%d%d", &x, &y))
        {
            if(!x && !y) break;
            a[i].l = x, a[i].r = y;
            i++;
        }
        n = i;
        solve();
        if(T) printf("\n");
    }
    return 0;
}

 

 

posted on 2012-10-15 21:50  有间博客  阅读(776)  评论(0编辑  收藏  举报