<题目链接>

题目大意:

给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数字周围8个点都不能取,问:取得数字的最大和为多少?

解题分析:

由于对每一个数,有选和不选两种可能,分别对应状态压缩中的1和0,且 n<=15,1<<15不是非常大,因此就可以非常自然的想到状态压缩。

此题要与普通的状压dp不同的是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,就是下面的bit数组,还有要注意一下输入。

  1. #include<cstdio> //此题要掌握的是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,就是下面的bit数组
  2. #include<iostream> //还要注意如何读入的格式,挺难的
  3. #include<cstring>
  4. #include <algorithm>
  5. #define N (1<<15)+10
  6. int dp[][N];//dp表示第i行j方案时获得的最大值
  7. int a[][], t[N], cnt, n, bit[N];//cnt存合法方案总数
  8. using namespace std;
  9.  
  10. void init() //此题要掌握的技巧是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,就是下面的bit数组
  11. {
  12. bit[] = ;
  13. for (int i = ; i <= n; i++) //存下2的1~15次方,与之后的状态比较
  14. bit[i] = bit[i - ] << ; //bit[2]为2的1次方,bit[3]为2的二次方
  15. }
  16.  
  17. void solve()
  18. {
  19. int i, j, k, l;
  20. cnt = ;
  21.  
  22. memset(dp, , sizeof(dp));
  23. for (i = ; i< ( << n) - ; i++) //用二进制存方案,每行最多有(1<<n)-1中方案,包括不合法方案
  24. {
  25. if (((i << )&i) == ) //判断方案i是否相邻两格均为1
  26. {
  27. for (j = ; j <= n; j++)
  28. if ((bit[j] & i)) //这个技巧一定要掌握,非常妙***
  29. dp[][i] += a[][j]; //先处理第一行的所有方案 dp[1][i]表示第一行取第i种方案时,在第一行得到的所有数的总数
  30. t[++cnt] = i; //这里的t[]数组也同时表示每一行的合法情况(只用一行中选取的数不相邻这一条件来约束时)
  31. }
  32. } //初始化dp数组,为下面的状态转移方程做好递推准备
  33.  
  34. for (i = ; i <= n; i++)
  35. {
  36. for (j = ; j <= cnt; j++)
  37. {
  38. int posn = ;
  39. for (k = ; k <= n; k++)
  40. if (bit[k] & t[j])
  41. posn += a[i][k];
  42. for (l = ; l <= cnt; l++) //这里的 t[j]&t[l]就是用来判断第i行取j方案时,是否与它上一行取的数,有相邻的,如果有,则这种方案舍弃
  43. if ((t[j] & t[l]) == && ((t[l] << )&t[j]) == && (t[l] >> & t[j]) == ) // t[l]<<1 & t[j] 和 t[l]>>1&t[j] 则是分别判断第i行取的数是否与它右上和左上的数相邻,如果相邻,也舍弃
  44. dp[i][t[j]] = max(dp[i][t[j]], posn + dp[i - ][t[l]]);
  45. } //dp[i][t[j]]表示当第i行选第j种方案时,前i行能取的数的最大总和
  46. }
  47. }
  48.  
  49. int main()//状态压缩dp,状态最多有(2<<15)-1种
  50. {
  51. int i, j;
  52. char str[];
  53. while (gets_s(str))
  54. {
  55. memset(a, , sizeof(a));
  56. n = ;
  57. for (i = ; i < strlen(str); i += ) {
  58. a[][++n] = (str[i] - '') * + (str[i + ] - '');
  59. }
  60. for (i = ; i <= n; i++)
  61. {
  62. gets_s(str);
  63. int m = ;
  64. for (j = ; j < strlen(str); j += ) {
  65. a[i][m++] = (str[j] - '') * + (str[j + ] - '');
  66. }
  67. }
  68. getchar();
  69. //以上为读入矩阵,这个输入还是要注意
  70.  
  71. init();
  72. solve();
  73. int res = ;
  74. for (i = ; i <= cnt; i++)
  75. if (res<dp[n][t[i]]) //dp[i][j]表示当第i行选第j种方案时,前i行能取的数的最大总和
  76. res = dp[n][t[i]];
  77. printf("%d\n", res);
  78. }
  79. return ;
  80. }

2018-07-26

hdu 2167 方格取数 【状压dp】(经典)的更多相关文章

  1. HDU 1565 方格取数 状压dp

    题目: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多 ...

  2. 方格取数--状压DP or 网络流

    题意:http://acm.hdu.edu.cn/showproblem.php?pid=1565 取不相邻的点是权值最大. 这题可以网络流做,暂时先DP一下,网络流明天学一下~~ #define I ...

  3. HDU 1565 方格取数(1) 轮廓线dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...

  4. HDU 1565 方格取数(1) ——插头DP

    [题目分析] 其实直接状压就可以了. 但是有点闲,又写了一个可读性极差,智商低下,很(gou)好(pi)的代码 [代码] #include <cstdio> #include <cs ...

  5. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  6. 特殊方格棋盘【状压DP】

    特殊方格棋盘[状压DP] 讲真状压DP这个东西只不过是有那么亿丢丢考验心态罢了(确信) 先从板子题说起,另加一些基础知识 题目描述 在的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方 ...

  7. 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

      HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...

  8. hdu 1565 方格取数(1) 状态压缩dp

    方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  9. hdu 1565 方格取数(1)(状态压缩dp)

    方格取数(1)                                                                 Time Limit: 10000/5000 MS (J ...

随机推荐

  1. luogu P2515 [HAOI2010]软件安装

    传送门 看到唯一的依赖关系,容易想到树型dp,即\(f_{i,j}\)表示选点\(i\)及子树内连通的点,代价为\(j\)的最大价值,然后就是选课那道题 但是要注意 1.题目中的依赖关系不一定是树,可 ...

  2. HDU4738 Caocao's Bridges【强连通】

    题意: 曹操有N个岛,这些岛用M座桥连接起来,每座桥有士兵把守(也可能没有),周瑜想让这N个岛不连通,但只能炸掉一座桥,并且炸掉一座桥需要派出不小于守桥士兵数的人去,桥的守兵数为0时,也需要派出一个人 ...

  3. Struts自定义拦截器&拦截器工作原理

    0.拦截器的调用原理: 拦截器是一个继承了序列化接口的普通接口.其工作原理是讲需要被拦截的对象作为参数传到intercept()方法内,在方法内部对此对象进行处理之后再执行原方法.intercept( ...

  4. 【逆向笔记】OD工具使用-逆向TraceMe.exe

    名词注释 System breakpoint:系统断点,OllyDbg用CreateProcessA加载DEBUG_ONLY_THIS_PROCESS参数执行,程序运行之后会触发一个INT13,在系统 ...

  5. 初识CPU卡、SAM卡/CPU卡简介、SAM卡简介 【转】

    初识CPU卡.SAM卡/CPU卡简介.SAM卡简介 IC卡按照接口方式可分为接触式卡.非接触式卡.复合卡:按器件技术可分为非加密存储卡.加密存储卡和CPU卡. 加密存储卡是对持卡人的认证,只有输入正确 ...

  6. Linux命令:pigz多线程压缩工具【转】

    学习Linux系统时都会学习这么几个压缩工具:gzip.bzip2.zip.xz,以及相关的解压工具.关于这几个工具的使用和相互之间的压缩比以及压缩时间对比可以看:Linux中归档压缩工具学习 那么P ...

  7. bootstrap 的媒体查询

    有时候需要对bootstap的样式自定义,比如说某个元素的“height”值,要放在与bootstrap媒体查询同步的样式里,才会兼容响应式布局. .container类是bootstrap的官方参考 ...

  8. OCM_第十七天课程:Section7 —》GI 及 ASM 安装配置 _管理和配置 GRID /实施 ASM 故障组 /创建 ACFS 文件系统

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  9. VS2013 "当前不会命中断点.还没有为该文档家在任何符号" 解决办法

    参考:http://blog.csdn.net/u010797208/article/details/40452797 亲测可行

  10. Storm的部署

    配置方案如下 node1 Nimbus zookeeper node2 Supervisor zookeeper node3 Supervisor zookeeper node4 Supervisor ...