题目链接
https://www.luogu.com.cn/problem/P1803
https://oiinhand.info/problem/show/3/1791
题目大意
我们可以把比赛抽象成线段,即在 n n n 条线段中,选取 k k k 条不重叠的线段,使得 k k k 最大。
样例图解:
不难看出,选择 0 − 2 0-2 0−2 和 2 − 4 2-4 2−4 的线段为最优解。
做法
28分 dfs
枚举每一个元素选或不选的情况,取最优解。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int l,r;
}a[1000010];
bool cmp(node aa,node b)
{
return aa.l < b.l;
}
int n;
int ans;
int res;
void dfs(int x,int y)
{
if (x > n)
{
ans = max(ans,res);
return ;
}
dfs(x + 1,y);
if (a[x].l >= a[y].r) res ++,dfs(x + 1,x),res --;
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i].l >> a[i].r;
sort(a + 1,a + n + 1,cmp);
dfs(1,0);
cout << ans << endl;
return 0;
}
记录:https://www.luogu.com.cn/record/35175946
70分 记忆化dfs
用一个数组( f [ i ] f[i] f[i] )表示目前 1 − i 1-i 1−i 条线段中最多可以选 f [ i ] f[i] f[i] 条。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int l,r;
}a[1000010];
bool cmp(node aa,node b)
{
return aa.l < b.l;
}
int n;
int ans;
int res;
int f[1000010];
void dfs(int x,int y)
{
if (x > n)
{
ans = max(ans,res);
return ;
}
if (res < f[x]) return ;
f[x] = res;
dfs(x + 1,y);
if (a[x].l >= a[y].r) res ++,dfs(x + 1,x),res --;
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++) cin >> a[i].l >> a[i].r;
sort(a + 1,a + n + 1,cmp);
dfs(1,0);
cout << ans << endl;
return 0;
}
记录:https://www.luogu.com.cn/record/35176049
100分 贪心
贪心思路:
要想选取尽量多的线段,最左边的一条的右端点就要尽可能靠左。
先选取右端点最靠左的一条线段,再将剩下的按右端点排序,能选的就选。
代码实现:
有了贪心的思路,代码就不难写了。
我们可以用结构体(struct)来存储线段。
struct node
{
int s,e;
}a[1000010];
其中,s
代表左端点,e
代表右端点。
排序可以用sort
实现。
bool cmp(node aa,node b)
{
return aa.e < b.e;
}
sort (a + 1,a + n + 1,cmp);
判断时,如果一条线段的左端点在上一条线段的右端点的右边,则符合条件。
int j = 1;
for (int i = 2;i <= n;i ++)
{
if (a[i].s >= a[j].e) k ++,j = i;
}
其中,k
表示答案(选择了多少条线段),j
表示上一条线段的编号。
完整代码:
#include<iostream>
#include<algorithm>
using namespace std;
int k = 1;
int n;
struct node
{
int s,e;
}a[1000010];
bool cmp(node aa,node b)
{
return aa.e < b.e;
}
int main()
{
cin >> n;
for (int i = 1;i <= n;i ++)
{
cin >> a[i].s >> a[i].e;
}
sort(a + 1,a + n + 1,cmp);
int j = 1;
for (int i = 2;i <= n;i ++)
{
if (a[i].s >= a[j].e) k ++,j = i;
}
cout << k;
return 0;
}