• JZOJ6367. 【NOIP2019模拟2019.9.25】工厂(factory)


    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);
    }
    
    
  • 相关阅读:
    八、JVM视角浅理解并发和锁
    七、JVM类加载机制
    六、JVM命令和工具
    五、jvm垃圾回收3(几种垃圾收集器)
    四、JVM垃圾回收2(垃圾收集算法)
    jvm引用类型
    三、JVM垃圾回收1(如何寻找垃圾?)
    【原创】Android 对话框的使用
    【原创】CMD常用命令:解决实际问题
    【原创】开机出现grub rescue,修复办法
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090952.html
Copyright © 2020-2023  润新知