题目链接:

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代码:

  1. const int N=5;
  2. const int M=105;
  3. int n,m,B[M],A[N][M];
  4. int f[1<<N][M];
  5. int main( )
  6. {
  7. int i,j,k,t,z,r,u,G,T=read( );
  8. while(T--)
  9. {
  10. read(n);
  11. read(m);;
  12. for(i=1; i<=n; i++)
  13. for(j=1; j<=m; j++)
  14. A[i][j]=read( );
  15. int S=(1<<n)-1;
  16. for(i=1; i<=m; i++)
  17. for(j=0; j<=S; j++)
  18. f[j][i]=0;
  19. for(i=1; i<=m; i++)
  20. {
  21. for(j=0; j<=S; j++)
  22. {
  23. for(k=j;; k=(k-1)&j)
  24. {
  25. u=0;
  26. for(t=0; t<n; t++)
  27. {
  28. r=0;
  29. for(z=1; z<=n; z++)
  30. {
  31. G=((z-1)+t)%n+1;
  32. if(((1<<(G-1))&j)&&(!((1<<(G-1))&k)))
  33. r+=A[z][i];
  34. }
  35. u=max(u,r);
  36. }
  37. f[j][i]=max(f[j][i],f[k][i-1]+u);
  38. if(!k) break;
  39. }
  40. }
  41. }
  42. printf("%d\n",f[S][n]);
  43. }
  44. return 0;
  45. }

  

hard代码:

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define pii pair<int,int>
  4. using namespace std;
  5. const int maxn=12+10;
  6. const int maxm=2007;
  7. int num[maxn][maxm];
  8. pii p[maxn*maxm];
  9. int lis[maxn][maxn],cnt;
  10. int dp[maxn][(1<<12)+10],f[maxn][(1<<12)+10];
  11. set<int>se;
  12. int main()
  13. {
  14. int T;
  15. scanf("%d",&T);
  16. while(T--){
  17. int n,m;
  18. scanf("%d %d",&n,&m);
  19. for(int i=1;i<=n;i++){
  20. for(int j=1;j<=m;j++){
  21. scanf("%d",&num[i][j]);
  22. p[(i-1)*m+j]=make_pair(num[i][j],j);
  23. }
  24. }
  25. sort(p+1,p+1+n*m);
  26. se.clear();
  27. for(int i=0;i<n*m;i++){
  28. se.insert(p[n*m-i].second);
  29. if(se.size()==n)break;//保留最多n列
  30. }
  31. int cnt=0;
  32. for(auto i:se){
  33. cnt++;
  34. for(int j=1;j<=n;j++)
  35. lis[j][cnt]=num[j][i];
  36. }
  37. m=cnt;
  38.  
  39. int len=(1<<n);
  40. memset(f,0,sizeof(f));
  41. for(int i=1;i<=m;i++)//预处理每列选择状态的最优解
  42. for(int choose=0;choose<len;choose++){
  43.  
  44. for(int j=1;j<=n;j++){
  45. int res=0;
  46. for(int k=1;k<=n;k++){
  47. int g=(k-1+j)%n+1;
  48. if((1<<(g-1))&choose)res+=lis[k][i];
  49. }
  50. f[i][choose]=max(res,f[i][choose]);
  51. }
  52.  
  53. }
  54. memset(dp,0,sizeof(dp));
  55. for(int i=1;i<=m;i++){
  56. for(int choose=0;choose<len;choose++){
  57. for(int shift=choose;;shift=((shift-1)&choose)){//枚举choose的子集
  58. int v=choose-(shift&choose);
  59. dp[i][choose]=max(dp[i][choose],dp[i-1][shift]+f[i][v]);
  60. if(shift==0)break;
  61. }
  62. }
  63. }
  64. printf("%d\n",dp[m][len-1]);
  65. }
  66. return 0;
  67. }

  

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. (八)Struts标签基础(一)

    一.Struts标签分类 二.标签的使用 2.1 标签的主题 主题的设置与struts.xml中的常量<constant name="struts.ui.theme" val ...

  2. (七)Action之ActionContext(OGNL表达式的使用)

    一.ActionContext的重要性 struts中的数据都存放在ActionContext里,所以这部分是Action中的核心. ActionContext又称广义值栈,既然有广义值栈就有侠义值栈 ...

  3. Spring Boot Redis 分布式缓存的使用

    一.pom 依赖 <!-- 分布式缓存 --> <dependency> <groupId>org.springframework.boot</groupId ...

  4. 奇妙的算法【7】-贪婪算法-dp

    问题1描述:[贪婪算法,Dijistra算法] ①有一只兔子要从一个N*N的二维矩阵方格中从上跳到下面: ②每次只能向左或向下,越过一个方格,跳到下一个方格中: ③被越过的方格中的数值,表示该兔子越过 ...

  5. Node初始以及环境搭建(Node01)

    1. 相关概念 •什么是JavaScript? •一种遵守ECMAScript标准的脚本语言 •最初只能运行在浏览器端 •浏览器中的 JavaScript 可以做什么? •操作DOM:表单验证.动画 ...

  6. c#基础知识梳理(三)

    上期回顾 - https://www.cnblogs.com/liu-jinxin/p/10824638.html 一.方法 一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块.每一个 C ...

  7. 使用 keytool 生成安卓应用程序签名

    下载 keytool jar包: 解压jar包到固定目录 如: cd  /Library/Java/JavaVirtualMachines/ 进入到jar包目录: cd /Library/Java/J ...

  8. 一:项目简介(node express vue elementui axios)

    一:项目基本构造 ** 项目一共有 16 个页面,是一个电商网销项目,自己在网上的某网上找的一个要做的网站的设计图: 页面主要包括:  登录页 -- 注册页 -- 首页 -- 产品列表页 -- 产品详 ...

  9. golang包管理工具

    软件开发中,不可避免的会使用到第三方库,因此包管理工具可以极大的方便开发者管理第三方依赖,避免掉入"依赖地狱". 作为google强大背书的golang语言,golang官方包管理 ...

  10. MySQL脏读、虚读、幻读

    事务的特性: 原子性:指处于同一个事务中的多条语句是不可分割的. 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态.比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K. 隔离 ...