SDUT 2074 区间覆盖问题(贪心)

问题描述

Problem Description

用i来表示x坐标轴上坐标为[i-1,i]的长度为1的区间,并给出n(1≤n≤200)个不同的整数,表示n个这样的区间。
现在要求画m条线段覆盖住所有的区间,
条件是:每条线段可以任意长,但是要求所画线段的长度之和最小,
并且线段的数目不超过m(1≤m≤50)。

Input

输入包括多组数据,每组数据的第一行表示区间个数n和所需线段数m,第二行表示n个点的坐标。
Output

每组输出占一行,输出m条线段的最小长度和。
Sample Input

5 3
1 3 8 5 11
Sample Output

7

分析 & 代码

思路:可以先计算最大的点与最小的点之间的区间距离,然后将所有的点之间的区间长度从大到小依次删除,知道划分为m段,也就是一开始得到的是一条线段(覆盖所有的区间),然后减去一段最大的区间距离,这时候原来的那条线短就变成了两段….以此类推直到成为m段。

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define inf 0x3f3f3f3f
int n,m;
int sav[205];            //保存点
int minu[205];           //保存区间长度
int maxx;
int minn;
bool cmp(int a, int b){
    return a>b;
}
int main(){
    int len;
    while(cin>>n>>m){
        maxx = -inf;
        minn = inf;
        for(int i=0; i<n; i++){
            cin>>sav[i];
            if(sav[i]>maxx)
                maxx = sav[i];
            if(sav[i]<minn)
                minn = sav[i];        //先找到最大点 与最小点
        }
        len = maxx + 1 -minn;        //注意因为是区间 所以不是直接相减 还要多减1
        sort(sav, sav+n);            //对点进行排序
        for(int i=1; i<n; i++){
            minu[i-1] = sav[i]-1-sav[i-1];       //计算区间
        }
        sort(minu, minu+n-1, cmp);
        int i =0;
        while(m!=1){             //直到一条线段(长度为len)划为m条线段
            len -= minu[i++];
            m--;
        }
        cout<<len<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_34328764/article/details/80353300
今日推荐