邻面合并(merging)

题目描述

给定一个N×MN×M的网格,每个格子上写有0或1。现在用一些长方形覆盖其中写有1的格子,长方形的每条边都要与坐标轴平行。要求:每个写着1的格子都要被覆盖,长方形不可以重叠(重复绘制也多少会增加性能开销),也不能覆盖到任何一个写着0的格子(不然绘制结果就不正确了)。请问最少需要多少长方形?

输入

输入文件第一行两个正整数N,MN,M,表示网格大小为NN行MM列。

接下来的NN行,每行MM个正整数AijAij(保证均为0或1),其中第ii行jj列的正整数表示网格ii行jj列里填的数。

输出

输出文件包含一行一个正整数,表示最少需要的长方形数量。

样例输入

  1. <span style="color:#333333"><span style="color:#333333">4 4
  2. 1 1 1 0
  3. 1 1 1 1
  4. 0 0 1 1
  5. 0 0 1 1</span></span>

样例输出

  1. <span style="color:#333333"><span style="color:#333333">3</span></span>

提示

样例解释

一种行的覆盖方案(粗线表示分割线):

数据范围

对于30% 的数据:N,M≤5N,M≤5。

对于100% 的数据:N≤100,M≤8N≤100,M≤8。

来源


solution

状压dp,我想不到

令f[i][S]表示前i行,状态为S

状态为1表示是一个新的开始

比如状态10010

表示划成了2个矩形,开头在1 4

转移时枚举是否能接起来

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<cmath>
  7. #define inf 1e9
  8. using namespace std;
  9. int n,m,s[105][10],f[102][1<<9];
  10. int num=0;
  11. bool pd(int k,int S){
  12. for(int i=0;i<m;i++){
  13. int t=(1<<i);
  14. if((S&t)&&s[k][i]==0)return 0;
  15. }
  16. int fl=0;
  17. for(int i=0;i<m;i++){
  18. int t=(1<<i);
  19. if(S&t)fl=1;
  20. if(s[k][i]==1&&!fl)return 0;
  21. if(s[k][i]==0)fl=0;
  22. }
  23. return 1;
  24. }
  25. int cost(int k,int S,int T){
  26. int sum=0;
  27. for(int i=0;i<m;i++){
  28. int t=(1<<i);
  29. if(S&t)sum++;
  30. }
  31. for(int i=0;i<m;i++){
  32. int t=(1<<i);
  33. if((S&t)&&(T&t)){
  34. int ed=i;for(;s[k][ed]&&ed<=m;ed++)if(ed!=i&&(S&(1<<ed)))break;
  35. //cout<<"ed "<<ed<<' '<<i<<endl;
  36. bool fl=0;
  37. for(int j=i+1;j<ed;j++)if(T&(1<<j)){fl=1;break;}
  38. for(int j=i+1;j<ed;j++)if(!s[k-1][j]){fl=1;break;}
  39. if(!fl&&((T&(1<<ed))||!s[k-1][ed]))sum--;
  40. }
  41. }
  42. return sum;
  43. }
  44. int main()
  45. {
  46. cin>>n>>m;
  47. for(int i=1;i<=n;i++){
  48. for(int j=0;j<m;j++){
  49. scanf("%d",&s[i][j]);
  50. }
  51. }
  52. for(int i=0;i<=n;i++)
  53. for(int j=0;j<(1<<m);j++)f[i][j]=inf;
  54. f[0][0]=0;
  55. for(int i=1;i<=n;i++){
  56. for(int S=0;S<(1<<m);S++){
  57. if(pd(i,S)){
  58. for(int T=0;T<(1<<m);T++){
  59. if(f[i-1][T]!=inf){
  60. //cout<<i<<' '<<S<<' '<<T<<endl;
  61. f[i][S]=min(f[i][S],f[i-1][T]+cost(i,S,T));
  62. //cout<<cost(i,S,T)<<endl;
  63. //system("pause");
  64. }
  65. }
  66. }
  67. }
  68. }
  69. int ans=inf;
  70. for(int S=0;S<(1<<m);S++)ans=min(ans,f[n][S]);
  71. cout<<ans<<endl;
  72. return 0;
  73. }

邻面合并(merging)的更多相关文章

  1. [CSP-S模拟测试]:邻面合并(状压DP)

    题目背景 $NEWorld$作为一个$3D$游戏,对渲染(图形绘制)的效率要求极高.当玩家扩大视野范围时,可见的方块面数量将会迅速增多,以至于大量的顶点处理很快就成为了图形管线中的瓶颈.乔猫想了想,决 ...

  2. [HNOI2009]梦幻布丁 算法技巧之邻接链

    题目描述 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. 输入输出格式 输入格式: 第 ...

  3. 理解 Git 的基本概念 ( Merging Collaborating Rebasing)

    合并 Merging 在分支上开发新功能后,如何把新功能加入到主分支,让其它人得到你的修改呢?你需要使用命令 git merge 或 git pull. 这两个命令的语法如下: git merge [ ...

  4. NOIP模拟80

    学考+OJ改名祭 T1 邻面合并 解题思路 状压 DP ...(于是贪心竟然有 60pts 的高分?? code) 状态设计的就非常妙了,如果状态是 1 就表示是一个分割点也就是一个矩形的右边界. 那 ...

  5. Noip模拟80 2021.10.18

    预计得分:5 实际得分:140?????????????? T1 邻面合并 我考场上没切掉的大水题....(证明我旁边的cty切掉了,并觉得很水) 然而贪心拿了六十,离谱,成功做到上一篇博客说的有勇气 ...

  6. elasticseach multi-field的实际用途

    下面是multi-field的介绍: multi_field 多域类型允许你对同一个值以映射的方式定义成多个基本类型 core_types . 这个非常有用,比如,如果你定义一个 string 类型的 ...

  7. TortoiseSVN中图标的含义

    今天在使用svn时发现有好多不认识了,所以查了下svn帮助手册.借此总结了下 svn 中图标的含义 一个新检出的工作复本使用绿色的勾做重载.表示Subversion状态 正常. 在开始编辑一个文件后, ...

  8. C语言动态内存管理

    1-概述 动态存储管理的基本问题是:系统如何按请求分配内存,如何回收内存再利用.提出请求的用户可能是系统的一个作业,也可能是程序中的一个变量. 空闲块 未曾分配的地址连续的内存区称为“空闲块”. 占用 ...

  9. Git让你从入门到精通,看这一篇就够了!

    简介 Git 是什么? Git 是一个开源的分布式版本控制系统. 什么是版本控制? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 什么是分布式版本控制系统? 介绍分布 ...

随机推荐

  1. python_18_三元运算

    # result=值1 if 条件 else 值2 如果条件为真:result=值1,否则result=值2. a,b,c=1,3,5 d=a if b>c else c print(d)

  2. MicroService 微服务提供者搭建

    本机IP为  192.168.1.102 1.  新建Maven项目   microservice 2.   pom.xml <project xmlns="http://maven. ...

  3. Linux命令安装vnc服务端与vnc的客户端

    第一歩:运行命令 yum install tigervnc-server -y 第二歩:安装telnet 第三歩:运行vncserver,创建桌面 vncserver -kill :1  删除桌面1的 ...

  4. 开发中经常遇到的一些css样式问题

    1.经常会遇到子元素浮动了,父元素就会探索到一个合适的值现在值是0,就要清除浮动操 <div class="search clearfix"> <div clas ...

  5. python 进度条 打印

  6. django+xadmin在线教育平台(三)

    通过留言版功能回顾django基础知识 将对于django目录结构,使用Django快速搭建可以提交的表单页面,models.py , urls.py, views.py. 从数据库中取出数据展示到h ...

  7. 爬取代理IP,并判断是否可用。

    # -*- coding:utf-8 -*- from gevent import monkey monkey.patch_all() import urllib2 from gevent.pool ...

  8. 06.VUE学习之非常实用的计算属性computed实例

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  9. MongDB之各种修改操作

    接口IMongDaoUpdate: package com.net.test.mongdb.dao; import com.net.test.mongdb.entity.User; public in ...

  10. python网络-多任务实现之协程(27)

    一.协程 协程,又称微线程,纤程.英文名Coroutine. 协程不是进程,也不是线程,它就是一个函数,一个特殊的函数——可以在某个地方挂起,并且可以重新在挂起处继续运行.所以说,协程与进程.线程相比 ...