UVA 10020 Minimal coverage

 

大意:数轴上有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;
}

 

 

你可能感兴趣的:(over)