题目

  点这里看题目。

分析

  插头 DP ,考虑枚举一下两块之间的分割线,本质上就是两个端点都在边界上的路径。

   DP 过程中,我们将没有端点在边界上面的路径称为 1 路径,反之叫 2 路径

  对于 1 路径,我们不能中途把它连成环,因此 1 路径的插头需要用括号序表示(最小整数也可以,只要能判掉连通性就可以了)。

  接着对插头分一下类:

  1.一条 1 路径的左端点,编号为 1 。

  2.一条 1 路径的右端点,编号为 2 。

  3.一条 2 路径的一个端点,编号为 3 。(如果有 3 插头,那么这个 2 路径的另一个端点就在边界上)

  由于插头只有 4 种情况,因此我们使用 4 进制来压缩状态。

  另外,我们只能在边界上放\(2\)个端点,因此需要再开一维来记录一下。

   DP 状态如下:

  \(f(i,j,S,c)\):格子\((i,j)\)的轮廓线状态为\(S\),并且在边界上放了\(c\)个端点的方案数。

  转移嘛......写起来相当复杂,但是分类讨论本身不难想,所以想看就去代码里找吧qwq逃了。

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #define l j - 1
  4. #define u j
  5. #define d j - 1
  6. #define r j
  7. #define mov( x ) ( x << 1 )
  8. #define mp( x ) grid[x.first][x.second]
  9. const int MAXN = 20, MAXM = 20, MAXS = ( 1 << 20 ) + 5;
  10. //空间开大,不太清楚为什么qwq
  11. template<typename _T>
  12. void read( _T &x )
  13. {
  14. x = 0;char s = getchar();int f = 1;
  15. while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
  16. while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
  17. x *= f;
  18. }
  19. template<typename _T>
  20. void write( _T x )
  21. {
  22. if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
  23. if( 9 < x ){ write( x / 10 ); }
  24. putchar( x % 10 + '0' );
  25. }
  26. struct table
  27. {
  28. int f[MAXS], stk[MAXS], siz;
  29. table() { memset( f, 0, sizeof f ), memset( stk, 0, sizeof stk ), siz = 0; }
  30. int operator [] ( const int indx ) const { return f[stk[indx]]; }
  31. int operator () ( const int indx ) const { return stk[indx]; }
  32. void add( int S, int v ) { if( ! f[S] ) stk[++ siz] = S; f[S] += v; }
  33. void clear() { while( siz ) f[stk[siz --]] = 0; }
  34. };
  35. struct DP_Structure
  36. {
  37. table F[3];
  38. table& operator [] ( const int indx ) { return F[indx]; }
  39. void clear() { for( int i = 0 ; i < 3 ; i ++ ) F[i].clear(); }
  40. }dp[2];
  41. int stk[MAXM] = {}, top;
  42. int state[MAXM], matched[MAXM];
  43. int grid[MAXN][MAXN];
  44. int N, M, pre = 1, nxt = 0;
  45. void prepare() { pre ^= 1, nxt ^= 1, dp[nxt].clear(); }
  46. int get( int x, int y ) { return ( x >> mov( y ) ) & 3; }
  47. int clr( int x, int y ) { return x & ( ~ ( 3 << mov( y ) ) ); }
  48. int reset( int x, int y, int z ) { return clr( x, y ) | ( z << mov( y ) ); }
  49. int dbset( int x, int y, int a, int b = -1 ) { return reset( reset( x, y, a ), y + 1, ~ b ? b : a ); }
  50. void match()
  51. {
  52. for( int i = 0 ; i <= M ; i ++ )
  53. {
  54. if( state[i] == 1 ) stk[++ top] = i;
  55. if( state[i] == 2 ) matched[stk[top]] = i, matched[i] = stk[top --];
  56. }
  57. }
  58. int encode( int *sta )
  59. {
  60. int ret = 0;
  61. for( int i = M ; ~ i ; i -- ) ret = ( ret << 2 ) + sta[i];
  62. return ret;
  63. }
  64. void decode( int *sta, int val )
  65. {
  66. memset( sta, 0, MAXM * 4 );
  67. for( int i = 0 ; i <= M ; i ++ ) sta[i] = val & 3, val >>= 2;
  68. match();
  69. }
  70. int main()
  71. {
  72. int S, v, lef, up, mtL, mtU;
  73. read( N ), read( M );
  74. N ++, M ++;
  75. if( N > M ) N ^= M, M ^= N, N ^= M;
  76. for( int i = 2 ; i < N ; i ++ )
  77. for( int j = 2 ; j < M ; j ++ )
  78. grid[i][j] = 1;
  79. for( int i = 2 ; i < M ; i ++ ) grid[1][i] = grid[N][i] = 2;
  80. for( int i = 2 ; i < N ; i ++ ) grid[i][1] = grid[i][M] = 2;
  81. prepare();
  82. dp[nxt][0].add( 0, 1 );
  83. for( int i = 1 ; i <= N ; i ++ )
  84. {
  85. prepare();
  86. for( int c = 0 ; c <= 2 ; c ++ )
  87. for( int k = 1 ; k <= dp[pre][c].siz ; k ++ )
  88. if( ! get( dp[pre][c]( k ), M ) )
  89. dp[nxt][c].add( dp[pre][c]( k ) << 2, dp[pre][c][k] );
  90. for( int j = 1 ; j <= M ; j ++ )
  91. {
  92. prepare();
  93. for( int c = 0 ; c <= 2 ; c ++ )
  94. for( int k = 1 ; k <= dp[pre][c].siz ; k ++ )
  95. {
  96. S = dp[pre][c]( k ), v = dp[pre][c][k];
  97. lef = get( S, l ), up = get( S, u );
  98. if( grid[i][j] == 0 ) { if( ! lef && ! up ) dp[nxt][c].add( S, v ); continue; }
  99. decode( state, S );
  100. if( grid[i][j] == 2 )
  101. {
  102. dp[nxt][c].add( S, v );
  103. if( c == 2 ) continue;
  104. if( i == 1 ) { if( ! lef && ! up ) dp[nxt][c + 1].add( reset( S, d, 3 ), v ); }
  105. if( j == 1 ) { if( ! lef && ! up ) dp[nxt][c + 1].add( reset( S, r, 3 ), v ); }
  106. //在上边界与左边界放端点,会在轮廓线上新增 3 插头
  107. if( i == N )
  108. {
  109. if( lef || ! up ) continue;
  110. if( up == 3 ) dp[nxt][c + 1].add( dbset( S, d, 0 ), v );
  111. else
  112. {
  113. state[matched[u]] = 3, state[u] = 0;
  114. dp[nxt][c + 1].add( dbset( encode( state ), d, 0 ), v );
  115. }
  116. }
  117. if( j == M )
  118. {
  119. if( ! lef || up ) continue;
  120. if( lef == 3 ) dp[nxt][c + 1].add( dbset( S, d, 0 ), v );
  121. else
  122. {
  123. state[matched[l]] = 3, state[l] = 0;
  124. dp[nxt][c + 1].add( dbset( encode( state ), d, 0 ), v );
  125. }
  126. }
  127. //在下边界与右边界放端点,会与已有插头连接;如果已有插头不是 3 插头,就需要考虑 3 插头移动的情况
  128. }
  129. else
  130. {
  131. if( ! lef && ! up ) dp[nxt][c].add( S, v ), dp[nxt][c].add( dbset( S, d, 1, 2 ), v );
  132. if( lef && ! up ) dp[nxt][c].add( S, v ), dp[nxt][c].add( dbset( S, d, 0, lef ), v );
  133. if( ! lef && up ) dp[nxt][c].add( S, v ), dp[nxt][c].add( dbset( S, d, up, 0 ), v );
  134. if( lef && up )
  135. {
  136. mtL = matched[l], mtU = matched[u];
  137. state[d] = state[r] = 0;
  138. if( lef == 3 && up ^ 3 ) state[mtU] = 3;
  139. if( lef ^ 3 && up == 3 ) state[mtL] = 3;
  140. //考虑 3 插头移动的情况
  141. if( lef == 1 && up == 1 ) state[mtU] = 1;
  142. if( lef == 2 && up == 2 ) state[mtL] = 2;
  143. //正常括号转移
  144. if( lef ^ 1 || up ^ 2 ) dp[nxt][c].add( encode( state ), v );
  145. //需要把会连成环的情况判掉
  146. }
  147. }
  148. }
  149. }
  150. }
  151. write( dp[nxt][2][0] ), putchar( '\n' );
  152. return 0;
  153. }

[CQOI2007]矩形的更多相关文章

  1. BZOJ1259:[CQOI2007]矩形rect(DFS)

    Description 给一个a*b矩形,由a*b个单位正方形组成.你需要沿着网格线把它分成分空的两部分,每部分所有格子连通,且至少有一个格子在原矩形的边界上.“连通”是指任两个格子都可以通过水平或者 ...

  2. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  3. BZOJ 刷题总结(持续更新)

    本篇博客按照题号排序(带*为推荐题目) 1008 [HNOI2008]越狱 很经典的题了..龟速乘,龟速幂裸题,, 1010 [HNOI2008]玩具装箱toy* 斜率优化 基本算是裸题. 1012 ...

  4. [BOT] 一种android中实现“圆角矩形”的方法

    内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...

  5. C语言 · 矩形面积交

    问题描述 平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴.对于每个矩形,我们给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积. 输入格式 输入仅包含两行,每行描述一个矩形. 在每行中 ...

  6. canvas快速绘制圆形、三角形、矩形、多边形

    想看前面整理的canvas常用API的同学可以点下面: canvas学习之API整理笔记(一) canvas学习之API整理笔记(二) 本系列文章涉及的所有代码都将上传至:项目代码github地址,喜 ...

  7. [LeetCode] Perfect Rectangle 完美矩形

    Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover o ...

  8. [LeetCode] Rectangle Area 矩形面积

    Find the total area covered by two rectilinear rectangles in a2D plane. Each rectangle is defined by ...

  9. [LeetCode] Maximal Rectangle 最大矩形

    Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and ...

随机推荐

  1. Request.params,Request.form,Request.querystring区别(转)

    自己总结:---大致意思是: 1.传参的方式分为:get方式传参,post方式传参,request.cookies和request.servervariables 2.这几种获取参数方式获取的都是一个 ...

  2. 关于 Git 拉取GitLab工程报错:Repository not found的问题

    [root@localhost xscan]# git pull fatal: repository 'http://gitlab.***.com/***.git/' not found 原因1: 可 ...

  3. springmvc数据处理-中文乱码

    首先解决中文乱码 通过mvc过滤器解决,在web.xml中配置 <filter> <filter-name>CharacterEncodingFilter</filter ...

  4. Fragment简介及使用

    概述 Fragment是 Android 3.0(API 11)引入的一种设计,用于大屏幕的设备. Fragment依托于Activity,受宿主Activity生命周期的影响.但它也有自己的生命周期 ...

  5. CopyOnWriteArrayList(写入并复制) & CountDownLatch(闭锁)

    ConcurrentHashMap: ①Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器 的性能.② ConcurrentHashMap 同步容器 ...

  6. nodejs版本代码注释率统计上新啦~~~

    github链接在这 Installation $ npm install jscrs -g Usage $ npx jscrs or $ jscrs options 不建议使用自定义配置 confi ...

  7. Java多线程通关——基础知识挑战

    等掌握了基础知识之后,才有资格说基础知识没用这样的话.否则就老老实实的开始吧.     对象的监视器 每一个Java对象都有一个监视器.并且规定,每个对象的监视器每次只能被一个线程拥有,只有拥有它的线 ...

  8. prometheus配置pushgateway功能测试

    一.环境: 1.prometheus服务器ip:192.168.0.208 2.node-exporter客户机ip:192.168.0.202 二.测试设计考虑: pushgateway类似一台信息 ...

  9. Spring boot Sample 0010之spring-boot-web-freemarker

    一.环境 1.1.Idea 2020.1 1.2.JDK 1.8 二.目的 spring boot 整合freemarker模板开发web项目 三.步骤 3.1.点击File -> New Pr ...

  10. 【JVM】垃圾回收器总结(2)——七种垃圾回收器类型

    七种垃圾回收器类型 GC的约定参数 DefNew——Default New Generation Tenured——Serial Old ParNew——Parallel New Generation ...