题目链接:

https://codeforces.com/contest/1209/problem/E2

题意:

给出$n$行和$m$列

每次操作循环挪动某列一次

可以执行无数次这样的操作

让每行最大值的累加和最大

数据范围:

$1\leq n \leq 12$

$1\leq m \leq 20000$

分析:

定义$dp[i][j]$,考虑前$i$列,选择状态为$j$的最大值

$ans=dp[m][(1<<n)-1]$

$dp[i][j]$可以由$dp[i-1][k]$转移,$k$是$j$的二进制子集

$easy$难度还是比较好写的

$hard$难度需要预处理,和保留最多$n$列

easy代码:

const int N=5;
const int M=105;
int n,m,B[M],A[N][M];
int f[1<<N][M];
int main( )
{
int i,j,k,t,z,r,u,G,T=read( );
while(T--)
{
read(n);
read(m);;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
A[i][j]=read( );
int S=(1<<n)-1;
for(i=1; i<=m; i++)
for(j=0; j<=S; j++)
f[j][i]=0;
for(i=1; i<=m; i++)
{
for(j=0; j<=S; j++)
{
for(k=j;; k=(k-1)&j)
{
u=0;
for(t=0; t<n; t++)
{
r=0;
for(z=1; z<=n; z++)
{
G=((z-1)+t)%n+1;
if(((1<<(G-1))&j)&&(!((1<<(G-1))&k)))
r+=A[z][i];
}
u=max(u,r);
}
f[j][i]=max(f[j][i],f[k][i-1]+u);
if(!k) break;
}
}
}
printf("%d\n",f[S][n]);
}
return 0;
}

  

hard代码:

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int maxn=12+10;
const int maxm=2007;
int num[maxn][maxm];
pii p[maxn*maxm];
int lis[maxn][maxn],cnt;
int dp[maxn][(1<<12)+10],f[maxn][(1<<12)+10];
set<int>se;
int main()
{
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&num[i][j]);
p[(i-1)*m+j]=make_pair(num[i][j],j);
}
}
sort(p+1,p+1+n*m);
se.clear();
for(int i=0;i<n*m;i++){
se.insert(p[n*m-i].second);
if(se.size()==n)break;//保留最多n列
}
int cnt=0;
for(auto i:se){
cnt++;
for(int j=1;j<=n;j++)
lis[j][cnt]=num[j][i];
}
m=cnt; int len=(1<<n);
memset(f,0,sizeof(f));
for(int i=1;i<=m;i++)//预处理每列选择状态的最优解
for(int choose=0;choose<len;choose++){ for(int j=1;j<=n;j++){
int res=0;
for(int k=1;k<=n;k++){
int g=(k-1+j)%n+1;
if((1<<(g-1))&choose)res+=lis[k][i];
}
f[i][choose]=max(res,f[i][choose]);
} }
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++){
for(int choose=0;choose<len;choose++){
for(int shift=choose;;shift=((shift-1)&choose)){//枚举choose的子集
int v=choose-(shift&choose);
dp[i][choose]=max(dp[i][choose],dp[i-1][shift]+f[i][v]);
if(shift==0)break;
}
}
}
printf("%d\n",dp[m][len-1]);
}
return 0;
}

  

codeforces#1290E2 - Rotate Columns (hard version)(子集dp)的更多相关文章

  1. Codeforces 1209E2. Rotate Columns (hard version)

    传送门 发现 $n$ 很小,考虑状压 $dp$,但是如果强行枚举列并枚举置换再转移复杂度太高了 考虑推推结论,发现我们只要保留列最大值最大的 $n$ 列即可,证明好像挺显然: 假设我们让列最大值比较小 ...

  2. Codeforces Round #584 E2. Rotate Columns (hard version)

    链接: https://codeforces.com/contest/1209/problem/E2 题意: This is a harder version of the problem. The ...

  3. Codeforces 219D. Choosing Capital for Treeland (树dp)

    题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...

  4. [BZOJ4416][SHOI2013]阶乘字符串(子集DP)

    怎么也没想到是子集DP,想到了应该就没什么难度了. 首先n>21时必定为NO. g[i][j]表示位置i后的第一个字母j在哪个位置,n*21求出. f[S]表示S的所有全排列子序列出现的最后末尾 ...

  5. loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】

    题目链接 loj300 题解 orz litble 膜完题解后,突然有一个简单的想法: 考虑到\(2\)是质数,考虑Lucas定理: \[{n \choose m} = \prod_{i = 1} { ...

  6. hdu 5823 color II —— 子集DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5823 看博客:http://www.cnblogs.com/SilverNebula/p/5929550. ...

  7. BZOJ 4006 [JLOI2015]管道连接(斯坦纳树+子集DP)

    明显是一道斯坦纳树的题. 然而这题只需要属性相同的点互相连接. 我们还是照常先套路求出\(ans[s]\). 然后对\(ans[s]\)做子集DP即可. 具体看代码. #include<iost ...

  8. BZOJ 2560(子集DP+容斥原理)

    2560: 串珠子 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 757  Solved: 497[Submit][Status][Discuss] ...

  9. [CodeForces - 1272D] Remove One Element 【线性dp】

    [CodeForces - 1272D] Remove One Element [线性dp] 标签:题解 codeforces题解 dp 线性dp 题目描述 Time limit 2000 ms Me ...

随机推荐

  1. CCF 201803-1 跳一跳

    题目: 问题描述 近来,跳一跳这款小游戏风靡全国,受到不少玩家的喜爱. 简化后的跳一跳规则如下:玩家每次从当前方块跳到下一个方块,如果没有跳到下一个方块上则游戏结束. 如果跳到了方块上,但没有跳到方块 ...

  2. 最快得到MYSQL两个表的差集

    Mysql里不外乎就是 子查询 和 连接 两种方式. 设第一个表为table1, 第二个为table2, table1包含table2. sql为: //子查询 select table1.id fr ...

  3. 前端开发 Vue -1windows环境搭建Vue Node开发环境

    解决几个疑问: 想学习下vue.js,我理解的它是一个前端的框架,主要作用是对数据的处理,和juqery类似,所以不太理解为什么要在nodejs中npm install vue呢?在html文件中引入 ...

  4. Linux基本命令 vi操作和插件

    基本命令 vim命令 常用插件 基本命令 查看Tomcat日志: tail -n 20 -f catalina.out 查看指定列表: find ./ -name 'ser*' 搜索指定文件: loc ...

  5. C++编译 C # 调用方法

    C++编译    C # 调用方法 编译时使用  public ref class ABC {   ... }; 调用时  右键---引用 --- 添加dll引用  即可

  6. Uploadify 之使用

    uploadify 3.2.1是 jQuery提供的一个上传插件,其参数详解见 http://www.cnblogs.com/yangy608/p/3915349.html 这里列举一个实际应用的例子 ...

  7. 负载均衡之haproxy负载均衡算法及haproxy的工作模式

    haproxy负载均衡的算法有如下7种: .roundrobin : 基于权重轮循. static-rr : 基于权重轮循.静态算法,运行时改变无法生效 source : 基于请求源IP的算法.对请求 ...

  8. 解决sqoop抽数报错:IO Error: Connection reset

    遇到的问题:进行sqoop抽数时,虽然能成功执行,但是过程中有很多这样的信息 19/11/20 15:17:11 INFO mapreduce.Job: Task Id : attempt_15737 ...

  9. element-ui Drawer抽屉组件封装

    <template> <div class="com"> <el-drawer title="我是标题" :visible.syn ...

  10. 不常见的sql错误处理方法(1)

    select @@global.sql_mode, mysql5.7 导致 group查询出错 set @@global.sql_mode='' # mysql重启就失效了: phpstudy -&g ...