• CF1209题解


    E

    每列都可以沿下滚动若干次,使得各行最大值之和最大

    对每列的元素计算最大值,降序排,显然取前(min(n,m))个列处理即可

    比较巧妙的动规,设(f(i,S))为前(i)列,已经确定最大值集合为(S)的其集合的最大值(()通俗讲,对于每列,二进制枚举该列设定为最大值的行位置,该行其他值便不需要管了())

    考虑类似于背包的转换,对于每个(S),填表法去填一个空位置,(S)从小到大枚举,即可

    细节:滚动数组处理

    #include<bits/stdc++.h>
    typedef int LL;
    const LL maxn=13,maxm=2e3+9;
    inline LL Read(){
        LL x(0),f(1); char c=getchar();
        while(c<'0' || c>'9'){
            if(c=='-') f=-1; c=getchar();
        }
        while(c>='0' && c<='9'){
            x=(x<<3)+(x<<1)+c-'0'; c=getchar();
        }return x*f;
    }
    struct node{
    	LL x,id;
    }M[maxm];
    LL T;
    LL a[maxn][maxm],f[1<<maxn],g[1<<maxn],tmp[1<<maxn],fg[maxm],pos[1<<maxn];
    inline bool cmp(node xx,node yy){
    	return xx.x>yy.x;
    }
    inline LL Lowbit(LL x){
    	return x&(-x);
    }
    inline void Solve(LL n,LL m){
    	for(LL i=1;i<=m;++i) M[i]=(node){0,i},fg[i]=0;
    	for(LL i=1;i<=n;++i){
    		for(LL j=1;j<=m;++j){
    			a[i][j]=Read();
    			M[j].x=std::max(M[j].x,a[i][j]);
    		}
    	}
    	for(LL i=0;i<n;++i) pos[1<<i]=i+1;
    	std::sort(M+1,M+1+m,cmp);
    	for(LL i=1;i<=n && i<=m;++i)
    	    fg[M[i].id]=1;//,printf("%d ",M[i].id); puts("");
    	LL Len(1<<n);
    	for(LL i=0;i<Len;++i) f[i]=0;
    	for(LL i=1;i<=m;++i){
    		if(!fg[i]) continue;
    		for(LL bit=0;bit<Len;++bit) tmp[bit]=0;
    		
    		for(LL j=1;j<=n;++j){
    			for(LL bit=0;bit<Len;++bit) g[bit]=f[bit];
    			for(LL bit=0;bit<Len;++bit){
    				LL p(Len-1^bit);
    				while(p){
    					LL x(Lowbit(p)); LL nw(pos[x]);
    					g[bit|x]=std::max(g[bit|x],g[bit]+a[nw][i]);
    					p-=x;
    				}
    			}
    			LL tp(a[1][i]); for(LL k=1;k<n;++k) a[k][i]=a[k+1][i]; a[n][i]=tp;
    			for(LL bit=0;bit<Len;++bit) tmp[bit]=std::max(tmp[bit],g[bit]);
    		}
    		for(LL bit=0;bit<Len;++bit) f[bit]=tmp[bit];
    	}
    	printf("%d
    ",f[Len-1]);
    }
    int main(){
    	T=Read();
    	while(T--){
    		LL n(Read()),m(Read());
    		Solve(n,m);
    	}
    	return 0;
    }/*
    
    3
    2 3
    2 5 7
    4 2 4
    3 6
    4 1 5 2 10 4
    8 6 6 4 9 10
    5 4 9 5 8 7
    3 3
    9 9 9
    1 1 1
    1 1 1
    */
    

    F

    路径拆成单字符,多层图跑最短路

  • 相关阅读:
    第34周二
    JAVA数组的定义及用法
    最小生成树(普利姆算法、克鲁斯卡尔算法)
    再谈Hibernate级联删除——JPA下的Hibernate实现一对多级联删除CascadeType.DELETE_ORPHAN
    站点系统压力測试Jmeter+Badboy
    AfxMessageBox和MessageBox差别
    最长递增子序列
    JAVA Metrics 度量工具使用介绍1
    递归函数时间复杂度分析
    HDU 5052 LCT
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/11545905.html
Copyright © 2020-2023  润新知