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

状态表示:

设置状态$ 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. 使用Github快速的寻找项目

    作为一个3年的码农昨天在学习项目,顺便总结一下 ,在Github找项目的几个常用方式 ,如果对您有帮助,可以点个关注,便于下次光顾! 首先我们来看一下常用命令 1.指定搜索方式 搜索文件中有spiri ...

  2. Django + FastDFS (分布式远程服务器存储文件)

    之前随笔过一篇Docker来搭建分布式文件系统FastDfs就跳过了 https://www.cnblogs.com/xcsg/p/10901461.html FastDFS的Python  (dja ...

  3. Ubuntu虚拟机无网络连接的问题

    记录一下: 通过dhcp动态分配ip地址. sudo dhclient -v 应该就能解决了.

  4. day021|python之面向对象进阶1

    面向对象进阶 目录 面向对象进阶 1 继承 1.1 继承入门 1.1.1 继承基础 1.1.2 类的基本使用 1.2 多继承 1.2.1 多继承的基本使用 1.2.2 多继承以后的重复性 1.3 类的 ...

  5. [.NET] - 在Socket编程中遇到的问题总结

    问题1.无法访问已释放的对象. 对象名:"System.Net.Sockets.Socket" 产生这个scenario的原因是程序中的某个地方调用到了socket.close后, ...

  6. JDBC(五)—— 批量插入数据

    批量插入数据 @Test public void testInsert() throws Exception { Connection conn = null; PreparedStatement p ...

  7. 神奇的 SQL 之性能优化 → 让 SQL 飞起来

    开心一刻 一天,一个男人去未婚妻家玩,晚上临走时下起了大雨 未婚妻劝他留下来过夜,说完便去准备被褥,准备就绪后发现未婚夫不见了 过了好久,全身淋的像只落汤鸡的未婚夫回来了 未婚妻吃惊的问:" ...

  8. 【并发编程】- ThreadPoolExecutor篇

    Executor框架 Executor框架的两级调度模型(基于HotSpot) 在上层,Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定 ...

  9. 二、集群配置SSH免密登录

    一.以3个几点为例,分别为master.slave01.slave02 1.分别生成自己节点密钥对 master: 创建dsa免密代码:ssh-keygen -t dsa -P '' -f ~/.ss ...

  10. NVL函数:空值转换函数

    NVL(表达式1,表达式2) 如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值. 该函数的目的是把一个空值(null)转换成一个实际的值.其表达式的值可以是数字型.字符型和日期型. ...