Description
- 给定n个区间,将它们分成q组,使得每一组中的区间的并集不为空,所有组的并集大小之和最大。
- 保证题目至少存在一种合法的分配方案。
p<=n<=200
Solution
- 区间问题很容易想到的套路:考虑包含的区间之间的关系,通过某种转换将包含的区间去掉,然后就可以变成相交或相离的区间,排序后就可以很方便地DP。
- 这题也不例外。
- 如果一个区间x包含区间y,那么要么区间x单独一个,要么区间x跟y在一组。
- 因为如果x不是单独的话,去掉x会变优,加进y的组里也不会变劣。
- 有了这个性质就可以很好地DP了。
- 对于不包括其他区间的区间,排序后按顺序选就好了。
- 而其他的区间如果加进去对答案也没有影响。
- 剩下没有考虑过的贪心让他们选最长的就好了。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define maxn 205
using namespace std;
int n,m,i,j,k,l[maxn],r[maxn],tot1,p[maxn],tot2,q[maxn],bz[maxn];
int f[maxn][maxn];
int cmp1(int i,int j){return l[i]<l[j];}
int cmp2(int i,int j){return r[i]-l[i]>r[j]-l[j];}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
for(i=1;i<=n;i++) {
int tp=1;
for(j=1;j<=n;j++) if (i!=j&&!bz[j]&&l[i]<=l[j]&&r[j]<=r[i])
tp=0;
if (tp) p[++tot1]=i; else q[++tot2]=i,bz[i]=1;
}
sort(p+1,p+1+tot1,cmp1);
sort(q+1,q+1+tot2,cmp2);
memset(f,128,sizeof(f));
f[0][0]=0;
for(i=0;i<tot1;i++) for(j=0;j<m;j++) if (f[i][j]>=0){
for(k=i+1;k<=tot1&&r[p[i+1]]>l[p[k]];k++)
f[k][j+1]=max(f[k][j+1],f[i][j]+r[p[i+1]]-l[p[k]]);
}
int sum=0,ans=0;
for(i=0;i<=min(tot2,m);i++,sum+=r[q[i]]-l[q[i]])
ans=max(ans,sum+f[tot1][m-i]);
printf("%d",ans);
}