zoukankan      html  css  js  c++  java
  • 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);
    }
    
    
  • 相关阅读:
    二叉树遍历
    NO.35 2021/12/13(06:50)[周一]
    NO.29 2021/11/30(06:30)[周二]
    NO.22 2021/11/19(06:15) [周五]
    The .NET ORM Architec
    C#格式字符串
    C# Attribute
    .net DLL反编译文件
    【Beta】Scrum meeting1
    【Alpha】Scrum meeting 6
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090952.html
Copyright © 2011-2022 走看看