【动态规划】[luoguP1791]线段覆盖

来源:互联网 发布:网站编程语言培训机构 编辑:程序博客网 时间:2024/06/06 13:18

题目

首先将读入的数据进行排序 需要注意的是数据中线段的两个端点可能是逆序的 在输入的时候需要交换位置
然后就是DP的主要过程了 设f[i]表示从排序后的第1条线段到第i条线段中可以选取(不重合)的最多线段数 初始边界条件为f数组中的所有元素都是1 则状态转移方程为

fi=max(fi,fj+1)

且必须满足第i条与第j条不重合

代码如下

#include<iostream>#include<cstdio>#include<cctype>#include<algorithm>     using namespace std;    #define in = read();    typedef long long ll;    typedef unsigned int ui;    const ll size = 10000 + 100;        struct point{   int a , b;}data[size];            int n , p;            int maxx;             int f[size];inline ll read(){        ll num = 0 , f = 1;    char ch = getchar();        while(!isdigit(ch)){                if(ch == '-')   f = -1;                ch = getchar();        }        while(isdigit(ch)){                num = num*10 + ch - '0';                ch = getchar();        }        return num*f;}inline bool cmp(point a , point b){        if(a.a != b.a)  return a.a < b.a;        return a.b < b.b;}int main(){        n in;        for(register int i=1;i<=n;i++){                data[i].a in;   data[i].b in;                if(data[i].a > data[i].b)                        swap(data[i].a , data[i].b);                f[i] = 1;        }        sort(data + 1 , data + n + 1 , cmp);        for(register int i=2;i<=n;i++)                for(register int j=1;j<i;j++)                        if(data[i].a >= data[j].b)                                f[i] = max(f[i] , f[j] + 1);        for(register int i=1;i<=n;i++)                maxx = max(maxx , f[i]);        printf("%d\n" , maxx);        return 0;}//COYG
原创粉丝点击