【多题合集】线段覆盖1、2、3

1214 线段覆盖
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
给定x轴上的N(N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。

输入描述 Input Description
输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标。

输出描述 Output Description
输出第一行是一个整数表示最多剩下的线段数。

样例输入 Sample Input
3

6 3

1 3

2 5

样例输出 Sample Output
2

数据范围及提示 Data Size & Hint
0

#include
#include
#include
using namespace std;
struct x
{
int l;
int r;
}a[1001];
int comp(const x&a,const x&b)
{
if (a.r>b.r) return 0;
if (a.rreturn 1;
if (a.l>b.l) return 0;
if (a.l<=b.l) return 1;
}
int main()
{
int n;
int ans;
scanf("%d",&n);
ans=n;
for (int i=0;iscanf("%d%d",&a[i].l,&a[i].r);
if (a[i].l>a[i].r) swap(a[i].l,a[i].r);
    }
sort(a+0,a+n,comp);
int i=0;//i用来记录当前位置的线段
int ss=1;
while (i+ssif (a[i].r<=a[i+ss].l&&(i+ss//不相交时
{
i=i+ss;//更新状态,跳到与之比较的线段
ss=1;
}
else if (a[i].r>a[i+ss].l&&a[i].r<=a[i+ss].r&&(i+ss//部分相交
{
ans--;
ss++;
}
else if (a[i].r>a[i+ss].l&&a[i].r>a[i+ss].r&&(i+ss//覆盖,前一条比后一条长
{
ans--;
i++;
ss=1;
}
}

printf("%d",ans);
}

3027 线段覆盖 2
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
查看运行结果
题目描述 Description
数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大。

n<=1000

输入描述 Input Description
第一行一个整数n,表示有多少条线段。

接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci。

输出描述 Output Description
输出能够获得的最大价值
样例输入 Sample Input
3

1 2 1

2 3 2

1 3 4

样例输出 Sample Output
4

数据范围及提示 Data Size & Hint
数据范围

对于40%的数据,n≤10;

对于100%的数据,n≤1000;

0<=ai,bi<=1000000

0<=ci<=1000000

这道题与上题不同在于这里要求的是最大权值,留下的线段最多不一定代表权值最大所以用dp的方式更加合适(当然之前还是要排序),但是po主太弱了,乱搞出来一个程序然后就过了,怎么看都不像dp……

#include
#include
#include
using namespace std;
struct xd
{
int l,r,value;
}a[1001];
int f[1001],n;
int comp(xd x,xd y)
{
if (x.lreturn 1;
if (x.l>y.l) return 0;
if (x.rreturn 1;
if (x.r>=y.r) return 0;
if (x.value>y.value) return 0;
else return 1;
}
main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].value);
sort(a+1,a+n+1,comp);
for (int i=1;i<=n;i++) f[i]=a[i].value;
for (int i=1;i<=n;i++)
{
int maxn=0;
for (int j=1;j<=i;j++) if (a[j].r<=a[i].l)maxn=max(maxn,f[j]);//只要没有相交,那么我们就可以把它留下来,从第i条向前搜索,看看有没有和它不相交的。
f[i]+=maxn;
}
printf("%d",f[n]);
}


……
……

1643 线段覆盖 3
时间限制: 2 s
空间限制: 256000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
在一个数轴上有n条线段,现要选取其中k条线段使得这k条线段两两没有重合部分(端点可以重合),问最大的k为多少。

输入描述 Input Description
输入格式

输入文件的第1行为一个正整数n,下面n行每行2个数字ai,bi,描述每条线段。

输出描述 Output Description
输出格式

  输出文件仅包括1个整数,为k的最大值

样例输入 Sample Input
3

0 2

2 4

1 3

样例输出 Sample Output
2

数据范围及提示 Data Size & Hint
数据范围

对于20%的数据,n≤10;

对于50%的数据,n≤1000;

对于70%的数据,n≤100000;

对于100%的数据,n≤1000000,0≤ai<bi≤1000000。

无非就是数据变大了,把数组开大一点就可以了

#include
#include
#include
using namespace std;
struct x
{
    int l;
    int r;
}a[1000001];
int comp(const x&a,const x&b)
{
    if (a.r>b.r) return 0;
    if (a.rreturn 1;
    if (a.l>b.l) return 0;
    if (a.l<=b.l) return 1;
}
int main()
{
    int n;
    int ans;
    scanf("%d",&n);
    ans=n;
    for (int i=0;iscanf("%d%d",&a[i].l,&a[i].r);
    if (a[i].l>a[i].r) swap(a[i].l,a[i].r);
    }
    sort(a+0,a+n,comp);
    int i=0;
    int ss=1;
//  for (int i=0;i
    while (i+ssif (a[i].r<=a[i+ss].l&&(i+ss1;
        }
    else    if (a[i].r>a[i+ss].l&&a[i].r<=a[i+ss].r&&(i+sselse    if (a[i].r>a[i+ss].l&&a[i].r>a[i+ss].r&&(i+ss1;
        }
    }

    printf("%d",ans);
}

你可能感兴趣的:(【多题合集】线段覆盖1、2、3)