时间限制:0.75s

空间限制:65M

题意:

在一个n*m(n,m<=15)的网格中,每个格子有一个值,现在从网格中取出k(k<=n*m)个,保证在选中的格子中从任意一个格子去另外的所有格子最多只用到四种(上,下,左,右)操作中的两种,并使得到的值最大。输出该值和选中的格子坐标。


Solution

    从选中的网格的任意一个去所有格子只用两种操作:

左图一种满足条件的网格集合,右图的(1,3)到(3,2)必需使用(左,下,右)三种操作才能到达,是不符合要求的。

注意到,满足条件的网格集合一定不会出现凹形,因为凹形的上下两个突出点中的格子不可能只用两个操作到达。

由此用0,1记录左右两边是 向外突出还是向内收缩。

当一行的一边向内收缩时便不可以再向外突出了。

接下来是按行dp

f[row][l][r][opl][opr][k],代表第row行,取第l列带第r列的格子,左边格子突出状态为opl,右边为opr,当前共选择了k个格子

记录路径时如果用结构体记录下所有的状态的上一个状态需要15*15*2*2*225 * size(int)*6的空间.

爆一次内存后,想到对于上一个状态row和k可以推出,只需要记录(l,r,opl,opr)即可,而(l,r,opl,opr)都是不超过16的数,那么可以用一个int形用16进制存下

存的时候用 record=(l << 12) + (r << 8) + (opl << 4) + (opr)

用的时候

上一个(row,l,r,opl,opr,k)

可以由当前的(row - 1, (record >> 12) % 16, (record >> 8) % 16, (record >> 4) % 16, record % 16, k - r + l - 1)得到

这道题需要注意的地方有很多,不一一列举.总的来说是一道值得一做的好题

参考代码:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #define pdx pr[row][l][r][opl][opr][k]
  5. #define val(r,a,b) g[r][b] - g[r][a - 1]
  6. using namespace std;
  7. int f[16][16][16][2][2][230], g[16][16];
  8. int pr[16][16][16][2][2][230];
  9. int n, m, k, ans;
  10. int a, al, ar, aol, aor;
  11. /*
  12. op=0 / 左突
  13. op=1 \ 右突
  14. */
  15. //当前状态向下更新
  16. void update (int row, int l, int r, int opl, int opr, int s) {
  17. if (row == n) return ;
  18. for (int nl = (opl == 0 ? 1 : l); nl <= r; nl++)
  19. for (int nr = max (l, nl); nr <= (opr == 0 ? r : m); nr++) {
  20. int t1, t2;
  21. if (nl == l) t1 = opl;
  22. else
  23. t1 = (nl < l ? 0 : 1);
  24. if (nr == r) t2 = opr;
  25. else
  26. t2 = (nr < r ? 0 : 1);
  27. if (f[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] <
  28. f[row][l][r][opl][opr][s] + val (row + 1, nl, nr) ) {
  29. f[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] =
  30. f[row][l][r][opl][opr][s] + val (row + 1, nl, nr);
  31. //记录上一个状态 , 16进制状态压缩
  32. pr[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] =
  33. (l << 12) + (r << 8) + (opl << 4) + (opr);
  34. }
  35. }
  36. }
  37.  
  38. void dp() {
  39. for (int row = 1; row <= n; row++)
  40. for (int l = 1; l <= m; l++)
  41. for (int r = l; r <= m; r++)
  42. for (int opl = 0; opl < 2; opl++)
  43. for (int opr = 0; opr < 2; opr++) {
  44. f[row][l][r][opl][opr][r - l + 1] = g[row][r] - g[row][l - 1];
  45. for (int s = r - l + 1; s <= k; s++)
  46. if (f[row][l][r][opl][opr][s] > 0 ) {
  47. update (row, l, r, opl, opr, s);
  48. if (s == k)//记录最大解
  49. if (f[row][l][r][opl][opr][s] > ans) {
  50. ans = f[row][l][r][opl][opr][s];
  51. a = row, al = l, ar = r, aol = opl, aor = opr;
  52. }
  53. }
  54. }
  55. }
  56. //输出
  57. void write (int row, int l, int r, int opl, int opr, int k) {
  58. if (row == 0 || k <= 0) return;
  59. for (int i = l; i <= r; i++)
  60. printf ("%d %d\n", row, i);
  61. write (row - 1, (pdx >> 12) % 16, (pdx >> 8) % 16,
  62. (pdx >> 4) % 16, pdx % 16, k - r + l - 1);
  63. }
  64. int main() {
  65. #ifndef ONLINE_JUDGE
  66. freopen ("in.txt", "r", stdin);
  67. #endif // oline_judge
  68. scanf ("%d %d %d", &n, &m, &k);
  69. for (int i = 1; i <= n; i++)
  70. for (int j = 1; j <= m; j++) {
  71. scanf ("%d", &g[i][j]);
  72. g[i][j] += g[i][j - 1];
  73. }
  74. memset (f, -1, sizeof f);
  75. dp();
  76. printf ("Oil : %d\n", ans);
  77. write (a, al, ar, aol, aor, k);
  78. return 0;
  79. }

  

  

SGU 167.I-country的更多相关文章

  1. SGU 520 Fire in the Country(博弈+搜索)

    Description This summer's heat wave and drought unleashed devastating wildfires all across the Earth ...

  2. 新概念英语(1-67)The weekend

    新概念英语(1-67)The weekend What are the Johnsons going to do at the weekend? A:Hello. Were you at the bu ...

  3. SGU 分类

    http://acm.sgu.ru/problemset.php?contest=0&volume=1 101 Domino 欧拉路 102 Coprime 枚举/数学方法 103 Traff ...

  4. wifi的country code

    转自:http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.htmlCountry A 2 A 3 Number ------------- ...

  5. SGU 495. Kids and Prizes

    水概率....SGU里难得的水题.... 495. Kids and Prizes Time limit per test: 0.5 second(s)Memory limit: 262144 kil ...

  6. ural 1073. Square Country

    1073. Square Country Time limit: 1.0 secondMemory limit: 64 MB There live square people in a square ...

  7. ACM: SGU 101 Domino- 欧拉回路-并查集

    sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Desc ...

  8. 【SGU】495. Kids and Prizes

    http://acm.sgu.ru/problem.php?contest=0&problem=495 题意:N个箱子M个人,初始N个箱子都有一个礼物,M个人依次等概率取一个箱子,如果有礼物则 ...

  9. SGU 455 Sequence analysis(Cycle detection,floyd判圈算法)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=455 Due to the slow 'mod' and 'div' operati ...

随机推荐

  1. Linux Eclipse代码提示功能设置(Java & C/C++)

    最近在Linux下开发,由于长期使用Visual Studio 2010,对代码提示功能情有独钟,现在在Linux下,使用Eclipse做开发,当然免不了怀念Visual Studio强悍的代码提示, ...

  2. 数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋

    [题目描述] 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这棵大树实际上是一个带权 ...

  3. vijosP1285 佳佳的魔法药水

    vijosP1285 佳佳的魔法药水 链接:https://vijos.org/p/1285 [思路] 图论思想. 很巧妙. 如A+B=C,将AB之间连边,边权为C,用以找相连物品与合成物. 用Dij ...

  4. (转载)绿色版Mysql的安装配置

    本文出自于:http://johnnyhg.javaeye.com/blog/245544 一.下载MySQL http://www.mysql.org/downloads 我下载的是mysql-no ...

  5. [ReadingNotes] Search the links, static final in the java

    [ReadingNotes] Search the links, static final in the java */--> pre { background-color: #2f4f4f;l ...

  6. spring框架DI(IOC)和AOP 原理及方案

    http://www.blogjava.net/killme2008/archive/2007/04/20/112160.html http://www.oschina.net/code/snippe ...

  7. Calendar - SGU 115(日期判断)

    这年的开始的第一天是星期 1 代码如下: =============================================================================== ...

  8. [置顶] SVN服务器搭建和使用

    Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. 首先来下载和搭建SVN服务器. 现在Subversion已经迁移到apache网站上了,下载地址: http:// ...

  9. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(22)-权限管理系统-模块导航制作

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(22)-权限管理系统-模块导航制作 最近比较忙,系统难度独步增加,文章的发布速度明显比以前慢了. 由于我们 ...

  10. 使用dom4j解析xml文件,并封装为javabean对象

    dom4j是一个java的XML api,性能优异.功能强大.易于使用.这里使用dom4j对xml文件进行解析,并完成对文件的封装. 实现对xml文件的解析,主要使用到的是dom4j中的SAXRead ...