• 题解 CF1209E2 【Rotate Columns (hard version)】


    行很少,列很多。

    最终的答案只跟每一行有关,所以有些列是没用的。

    或者换个角度理解,我们按一列上的最大数将这 (m) 列排序,把第一列上的最大数放在第 1 行,第二列上的最大数房子第 2 行,……,把第 (n) 列上的最大数放在第 (n) 行。于是我们发现第 (n+1sim m) 列甚至连最大数都是没用的,况且前 (n) 列不仅会用到最大数,其它数也都有用到的可能,所以可能有用的列数只有 (min(n,m)) 条。

    接下来就考虑状压 DP,考虑状态 (f_{i,j}) 表示处理到排序后的第 (i) 列,行上的状态为 (j)(1 表示已经确定了最大数,0 表示没有确定最大数)中已经确定最大数的最大和。

    考虑转移,枚举子集,并计算子集的最大贡献,复杂度为 (O(3^nn^3)) 但这是无法接受的。

    我们发现瓶颈在于计算子集的最大贡献需要 (O(n^2)) 的复杂度,而一个子集可能会被计算多次,于是考虑提前预处理,得到复杂度为 (O(3^n n+2^nn^3))

    代码:

    #include<bits/stdc++.h>
    #define log(a) cerr<<"33[32m[DEBUG] "<<#a<<'='<<(a)<<" @ line "<<__LINE__<<"33[0m"<<endl
    #define LL long long
    #define SZ(x) ((int)x.size()-1)
    #define ms(a,b) memset(a,b,sizeof a)
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    #define DF(i,a,b) for(int i=(a);i>=(b);--i)
    using namespace std;
    inline int read(){char ch=getchar(); int w=1,c=0;
    	for(;!isdigit(ch);ch=getchar()) if (ch=='-') w=-1;
    	for(;isdigit(ch);ch=getchar()) c=(c<<1)+(c<<3)+(ch^48);
    	return w*c;
    }
    template<typename T>inline void write(T x){
        unsigned long long y=0;T l=0;
        if(x<0)x=-x,putchar(45);
        if(!x){putchar(48);return;}
        while(x){y=y*10+x%10;x/=10;l++;}
        while(l){putchar(y%10+48);y/=10;l--;}
    }
    template<typename T>inline void writeln(T x){write(x);puts("");}
    template<typename T>inline void writes(T x){write(x);putchar(32);}
    const int N=13,M=2010,K=(1<<N)+10;
    int f[N][K],a[N][M],t[K];
    struct Column{
    	int maxn,id;
    	inline bool operator<(const Column&t)const{
    		return maxn>t.maxn;
    	}
    }c[M];
    signed main(){
    	int _=read();while(_--){
    		int n=read(),m=read();
    		F(i,1,m)c[i].id=i,c[i].maxn=0;
    		F(i,1,n)
    			F(j,1,m){
    				a[i][j]=read();
    				c[j].maxn=max(c[j].maxn,a[i][j]);
    			}
    		sort(c+1,c+m+1);
    		F(i,1,min(n,m)){
    			F(j,0,(1<<n)-1){
    				t[j]=0;
    				F(k,0,n-1){
    					int sum=0;
    					F(l,0,n-1)
    						if((j>>l)&1)sum+=a[(l+k)%n+1][c[i].id];
    					t[j]=max(t[j],sum);
    				}
    			}
    			F(j,0,(1<<n)-1){
    				f[i][j]=f[i-1][j];
    				for(int k=j;k;k=(k-1)&j)
    					f[i][j]=max(f[i][j],f[i-1][j^k]+t[k]);
    			}
    		}writeln(f[min(n,m)][(1<<n)-1]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何把python最小化安装在客户机上面
    c++的历史-异常
    插件系统的构建
    ora-01445:无法从不带保留关键字的表的连接视图中选择ROWID或采样
    转--Oracle 审计和测试操作
    foreach属性-动态-mybatis中使用map类型参数,其中key为列名,value为列值
    C语言中 *.c和*.h文件的区别!
    解决方法:loadrunner 场景下执行webservice脚本是---报错10492 Error: Exception was raised when calling per-process-init function in extens
    NoSQL之Redis高级实用命令详解--安全和主从复制
    Expect安装方法
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/15139249.html
Copyright © 2020-2023  润新知