timus_1303_贪心

1303 最小覆盖  

  题目的大概意思:给一组线段[Li, Ri],Li, Ri都是整数,在这组线段中找出数量最少的线段使这些线段能完全覆盖[0,M]。

  输入:

  第一行整数M (1 ≤ M ≤ 5000)。

  后面是整数对,每对Li, Ri(abs(Li), abs(Ri) ≤ 50000)占一行。最后一行为0 0表示结束。

  输出:

  第一行打印完全覆盖[0,M]的最小线段数。

  后面打印覆盖[0,M]的线段,格式和输入一样。

  如果不存在完全覆盖则打印“No solution

  思路:尽量选择覆盖[0,M]长的线段,这也是很明显的,线段覆盖[0,M]越长,完全覆盖[0,M]所需要的线段数必然越少,所以这道题目可以使用贪心尽量选择覆盖[0,M]越长的线段,当然也可以用dp,只是效率差些。dp[k]表示完全覆盖[0,M]的最少线段数,dp[k] = dp[kk] + 1 ,其中kk满足min(0 <= kk < k, [kk, x], x >= k),我的策略是kk在满足(0 <= kk < k, [kk, x], x >= k)的条件下尽量选择最小的kk,这样覆盖[0,M]就会越长。另外一个贪心选择是对于输入,如果线段的左端点相同,只考虑线段长度最长的那个。还有就是对输入的处理,由于线段的两个端点可以是负数和超过5000,所以对于两个端点都是不超过0的数或者都是不小于M的数的线段都直接不予考虑,然后就是线段的左端点为负数的情况,一律将其看做左端点为0.

  代码:

#include <stdio.h>

typedef struct _pair
{
    int l;
    int r;
    int flag;
}pair_t;
pair_t segment[5001];
int dp[5001];
int path[5001];
int m;

void print(int n)
{
    if (n == -1)
        return;
    print(path[n]);
    printf("%d %d\n", segment[n].l, segment[n].r);
}
int main ( int argc, char *argv[] )
{
    int l, r;
    int i, j;
    int flag;

    scanf("%d", &m);
    while (1)
    {
        scanf("%d%d", &l, &r);    
        if (l == 0 &&  r == 0)
            break;
        if (l < 0 && r >= 0)    
        {
            if (segment[0].r < r)   //当左端点相同时,选择线段更长的 
            {
                segment[0].l = l;
                segment[0].r = r;
                segment[0].flag = 1;
            }
        }
        else if (l >= 0 && l <= m)  
        {
            if (segment[l].r < r)    
            {
                segment[l].l = l;
                segment[l].r = r;
                segment[l].flag = 1;
            }
        }
    }
    path[0] = -1;
    flag = 0;
    for (i = 1; i <= m; i ++)
    {
        for (j = 0; j <= i; j ++)
            if (segment[j].flag && segment[j].r >= i)
            {
                if (j == 0 || dp[j])    
                {
                    dp[i] = dp[j] + 1;
                    path[i] = j;
                }
                else
                    flag = 1;
                break;
            }
        if (j > i || flag)
            break;
    }
    if (i <= m)
        printf("No solution\n");
    else
    {
        printf("%d\n", dp[m]);
        print(path[m]);
    }
    return 0;
}                /* ----------  end of function main  ---------- */
原文地址:https://www.cnblogs.com/chengxuyuancc/p/3080454.html