• 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  ---------- */
  • 相关阅读:
    C#中两个不同时间的相加减以及时间比较
    C#中一些报错处理
    C#将DataGridView中的数据导出为EXCEL
    C# tabcontrol的tabpage切换
    C# DataGridView控件中数据导出到Excel
    C#将数据导入到excel中 出现 “object”未包含“get_Range”的定义
    SQL Server数据库的备份与还原以及在项目中是怎样去实现的 (网摘)
    android各组件详解
    刚刚做得一个Android开发教程的专题
    一个Demo让你掌握所有的android控件
  • 原文地址:https://www.cnblogs.com/chengxuyuancc/p/3080454.html
Copyright © 2020-2023  润新知