提供一种代码难度比较简单的做法(可能)

状态表示:

设置状态$ f[i][j] $,表示第 \(i\) 行状态为 \(j\) 的最大放置数,因为这是个阴间题,因为题目内存设置很小,所以要用滚动数组,存储两行的状态就够了。

状态用三进制表示:

0 表示当前行和上一行均可用
1 表示当前行可用,上一行不可用
2 表示当前行和上一行都不可用

为了方便不过常数确实略大,我们用两个数组 \(pre\) , \(now\) 分别存放上一行和当前行的状态

那么就有:

inline int getstate(int a[])//存放状态
{
int temp=0;
for(register int i=1;i<=m;i++)
temp+=a[i]*t[i];
return temp;
} inline int getstring(int temp,int*a)//取出状态
{
for(register int i=1;i<=m;i++)
{
a[i]=temp%3;
temp/=3;
}
}

判断放矩形(设要放矩形的左下角为 (i,j) ):

横放:

$ state(i,j)0 && state(i,j+1)0&& state(i,j+2)==0 \ \ \ \ \ $ \((j+2 \le m\),废话\()\)

竖放:

$ state(i,j)0 && state(i,j+1)0 && state(i-1,j)0 && state(i-1,j+1)0 $ $\ \ \ \ \ $ \((j+1 \le m\),二度废话\()\)

DP过程:

显然,当我们知道第\(i\)行状态,和第\(i-1\)行初始状态时,就可以愉快地DP了,因为状态转换略显复杂写成循环的话可能需要很多层,所以可以用大法师\(DFS\)来写。

设置dfs参数分别为,试图放置的坐标,放置矩形的数量,第\(i\)行状态:

如果足横放,竖放,不放的情况,分别搜一下就行。

Code:

#include<bits/stdc++.h>
using namespace std; int n,m,k,D;
int mp[151][15];
int f[2][59050];//f[i][j] i是滚动数组,j存放状态
int now[15],pre[15],t[15];//pre为i-1行,now为第i行 //0 表示当前行和上一行均可用
//1 表示当前行可用,上一行不可用
//2 表示当前行和上一行都不可用 inline int qr()
{
char a=0;int w=1,x=0;
while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
while(a<='9'&&a>='0'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
return x*w;
} inline int getstate(int a[])//存放状态
{
int temp=0;
for(register int i=1;i<=m;i++)
temp+=a[i]*t[i];
return temp;
} inline int getstring(int temp,int*a)//取出状态
{
for(register int i=1;i<=m;i++)
{
a[i]=temp%3;
temp/=3;
}
} void dfs(int i,int j,int num,int state)//(i,j)为尝试放矩形的右下角位置,num为放矩形数量,state为第i行状态
{
f[i%2][state]=max(f[i%2][state],num);//更新最大值
int k;
if(j>=m)
return ;
if(j<m-1&&now[j]==0&&now[j+1]==0&&now[j+2]==0)//这一行加上一行能横放一个
{
now[j]=now[j+1]=now[j+2]=2;
k=getstate(now);
dfs(i,j+3,num+1,k);
now[j]=now[j+1]=now[j+2]=0;
}
if(j<m&&pre[j]==0&&pre[j+1]==0&&now[j]==0&&now[j+1]==0)//这一行和上两行能竖放一个
{
now[j]=now[j+1]=2;
k=getstate(now);
dfs(i,j+2,num+1,k);
now[j]=now[j+1]=0;
}
dfs(i,j+1,num,state);//不放矩形
} int main()
{
D=qr();
t[1]=1;
for(register int i=2;i<=11;i++)
t[i]=t[i-1]*3;
while(D--)
{
n=qr();
m=qr();
k=qr();
memset(mp,0,sizeof(mp));
while(k--)
mp[qr()][qr()]=1;
for(register int i=0;i<t[m+1];i++)
f[1][i]=-1;
for(register int i=1;i<=m;i++)//第一行的上一行无法利用
pre[i]=mp[1][i]+1;//记录初始状态
int state=getstate(pre);
f[1][state]=0;
for(register int i=2;i<=n;i++)
{
for(register int j=0;j<t[m+1];j++)//预处理第i行状态
f[i%2][j]=-1;
for(register int j=0;j<t[m+1];j++)
{
if(f[(i+1)%2][j]==-1)
continue;
getstring(j,pre);//取出状态j
for(register int k=1;k<=m;k++)
{
if(mp[i][k]==1)//这个块坏了这一行跟上一行都用不了
now[k]=2;
else//块没坏
if(pre[k]==2)//上一行用不了
now[k]=1;//只能用本行
else
now[k]=0;//本行和上一行都能用
}
state=getstate(now);
dfs(i,1,f[(i+1)%2][j],state);//从j状态转移到state状态
}
}
int ans=0;
for(register int i=0;i<t[m+1];i++)//统计答案
ans=max(ans,f[n%2][i]);
printf("%d\n",ans);
}
return 0;
}

poj 1038 Bugs Integrated, Inc. 题解的更多相关文章

  1. POJ 1038 Bugs Integrated, Inc.(DFS + 三进制状压 + 滚动数组 思维)题解

    题意:n*m方格,有些格子有黑点,问你最多裁处几张2 * 3(3 * 2)的无黑点格子. 思路:我们放置2 * 3格子时可以把状态压缩到三进制: 关于状压:POJ-1038 Bugs Integrat ...

  2. POJ 1038 Bugs Integrated, Inc.

    AC通道 神坑的一道题,写了三遍. 两点半开始写的, 第一遍是直接维护两行的二进制.理论上是没问题的,看POJ discuss 上也有人实现了,但是我敲完后准备开始调了.然后就莫名其妙的以为会超时,就 ...

  3. POJ 1038 Bugs Integrated, Inc. ——状压DP

    状态压缩一下当前各格子以及上面总共放了几块,只有012三种情况,直接三进制保存即可. 然后转移的时候用搜索找出所有的状态进行转移. #include <map> #include < ...

  4. POJ 1038 Bugs Integrated Inc (复杂的状压DP)

    $ POJ~1038~~\times Bugs~Integrated~Inc: $ (复杂的状压DP) $ solution: $ 很纠结的一道题目,写了大半天,就想练练手,结果这手生的.其实根据之前 ...

  5. POJ 1038 Bug Integrated Inc(状态压缩DP)

    Description Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launchi ...

  6. [CEOI2002]Bugs Integrated, Inc. 题解

    又是一道神仙题,又是题解看不懂-- 好时代,来临力-- 时隔一个世纪来补题解了-- 之前太垃圾了,脑子有点问题,所以没看懂题解.今天再看这道题虽然还是很毒瘤,但也没有想象得那么难. 先观察芯片的形状, ...

  7. POJ1038 Bugs Integrated, Inc.

    题目来源:http://poj.org/problem?id=1038 题目大意: 有一家芯片公司要在一块N*M的板子上嵌入芯片,其中1<=N<=150, 1<=M<=10,但 ...

  8. poj 2096Collecting Bugs

    题目链接 poj 2096Collecting Bugs 题解 dp[i][j]表示已经找到i种bug,并存在于j个子系统中,要达到目标状态的天数的期望. 显然,dp[n][s]=0,因为已经达到目标 ...

  9. poj 2431 Expedition 贪心 优先队列 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=2431 题解 朴素想法就是dfs 经过该点的时候决定是否加油 中间加了一点剪枝 如果加油次数已经比已知最少的加油次数要大或者等于了 那么就剪 ...

随机推荐

  1. 图片放大缩小的zoom.js

    1 +function ($) { "use strict"; 2 3 /** 4 * The zoom service 5 */ 6 function ZoomService ( ...

  2. wordpress 后台富文本编辑器,添加图片发现无法左对齐,样式出现混乱

    如上图所示,无法左对齐,但是左对齐的按钮全部是正确的,最后一点点排除,发现是因为这个词的影响,去掉就好了,原因不明,可能是这个词被当做某个方法执行了

  3. PHP比较数组、对象是否为空

    PHP简单对比对象.数组是不是为空: 1 <?php 2 /*简单的比较对象和数组是不是为空*/ 3 4 #定义空类EmptyClass 5 class EmptyClass{} 6 7 $em ...

  4. flowable中使用到的一些方法。获取人员部门信息

    package org.springblade.desk.utils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf ...

  5. 怎么判断map不为空

    public static void main(String[] args) { Map<String, String> map = new HashMap<String, Stri ...

  6. JAVA_JNI字段描述符“([Ljava/lang/String;)V”(Android)

    JNI字段描述符"([Ljava/lang/String;)V "([Ljava/lang/String;)V" 它是一种对函数返回值和参数的编码.这种编码叫做JNI字段 ...

  7. JAVA程序通过JNI调用C/C++库

    java程序如何调用c/c++库中的函数主要分为三个步骤: 1. 加载库文件. System.loadLibrary 2. 找到函数( java函数<----映射---->c函数 ) 3. ...

  8. 高性能MySQL学习总结二----常见数据类型选择及优化

    一.数据类型的选择 MySQL的数据类型有很多种,选择正确的数据类型对于获得高性能特别地重要,如何选择合适的数据类型呢?主要遵从以下三个原则: 1.更小的通常情况下性能更好 一般情况下,应该尽量使用可 ...

  9. WEBSERVICE之CXF框架开发webservice

    之前学习了使用jdk开发webservice服务,现在开始学习使用框架(cxf)开发webservice. 1.准备工作 A.使用cxf开发webservice服务,需要用到apache-cxf-3. ...

  10. 搭建 Typecho 个人博客

    搭建 Typecho 个人博客 前言 最近在学习中,感觉有个自己的博客,用来记录学习总结,写写生活点滴是件不错的事. 在网上看到 Typecho 博客和 WordPress博客,顿时被 Typecho ...