poj 1038 Bugs Integrated, Inc. 题解
提供一种代码难度比较简单的做法(可能)
状态表示:
设置状态$ 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. 题解的更多相关文章
- POJ 1038 Bugs Integrated, Inc.(DFS + 三进制状压 + 滚动数组 思维)题解
题意:n*m方格,有些格子有黑点,问你最多裁处几张2 * 3(3 * 2)的无黑点格子. 思路:我们放置2 * 3格子时可以把状态压缩到三进制: 关于状压:POJ-1038 Bugs Integrat ...
- POJ 1038 Bugs Integrated, Inc.
AC通道 神坑的一道题,写了三遍. 两点半开始写的, 第一遍是直接维护两行的二进制.理论上是没问题的,看POJ discuss 上也有人实现了,但是我敲完后准备开始调了.然后就莫名其妙的以为会超时,就 ...
- POJ 1038 Bugs Integrated, Inc. ——状压DP
状态压缩一下当前各格子以及上面总共放了几块,只有012三种情况,直接三进制保存即可. 然后转移的时候用搜索找出所有的状态进行转移. #include <map> #include < ...
- POJ 1038 Bugs Integrated Inc (复杂的状压DP)
$ POJ~1038~~\times Bugs~Integrated~Inc: $ (复杂的状压DP) $ solution: $ 很纠结的一道题目,写了大半天,就想练练手,结果这手生的.其实根据之前 ...
- POJ 1038 Bug Integrated Inc(状态压缩DP)
Description Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launchi ...
- [CEOI2002]Bugs Integrated, Inc. 题解
又是一道神仙题,又是题解看不懂-- 好时代,来临力-- 时隔一个世纪来补题解了-- 之前太垃圾了,脑子有点问题,所以没看懂题解.今天再看这道题虽然还是很毒瘤,但也没有想象得那么难. 先观察芯片的形状, ...
- POJ1038 Bugs Integrated, Inc.
题目来源:http://poj.org/problem?id=1038 题目大意: 有一家芯片公司要在一块N*M的板子上嵌入芯片,其中1<=N<=150, 1<=M<=10,但 ...
- poj 2096Collecting Bugs
题目链接 poj 2096Collecting Bugs 题解 dp[i][j]表示已经找到i种bug,并存在于j个子系统中,要达到目标状态的天数的期望. 显然,dp[n][s]=0,因为已经达到目标 ...
- poj 2431 Expedition 贪心 优先队列 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=2431 题解 朴素想法就是dfs 经过该点的时候决定是否加油 中间加了一点剪枝 如果加油次数已经比已知最少的加油次数要大或者等于了 那么就剪 ...
随机推荐
- SQL注入及如何解决
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗 ...
- kafka rebalance解决方案 -incremental cooperative协议和static membership功能
apache kafka的重平衡(rebalance),一直以来都为人诟病.因为重平衡过程会触发stop-the-world(STW),此时对应topic的资源都会处于不可用的状态.小规模的集群还好, ...
- C# 链表 二叉树 平衡二叉树 红黑树 B-Tree B+Tree 索引实现
链表=>二叉树=>平衡二叉树=>红黑树=>B-Tree=>B+Tree 1.链表 链表结构是由许多节点构成的,每个节点都包含两部分: 数据部分:保存该节点的实际数据. 地 ...
- MySQL忘记密码了怎么解决
前言:在不考虑到原来用户对关联数据库的授权问题的情况下,有以下三种思路解决 #1.登录状态下修改 说明:在登录状态的话,直接使用命令修改密码就行了 mysql> use mysql; mysql ...
- ribbon源码分析
对于ribbon的使用我们只需要在RestTemplate的申明上面加上 @LoadBalanced 注解之后那么这个RestTemplate就具有了负载均衡的功能 ribbon是怎么实现这一功能的? ...
- Linux下登录Oracle命令行时删除键^H解决方法
Linux下登录Oracle命令行时删除键^H解决方法 在linux服务器下登录oracle的控制台,如果输入错误,想用删除键删除时却不能删除,输出的是^H的字符. 方法 用如下的命令可以使删除键生效 ...
- JIRA 知多少:聊一聊 Android Studio 、工作流相关设置
Android Studio 相关 配置 JIRA 服务器 如果细心的话会发现有一个选项卡:Commit Message.这一段代码是不是有点熟悉呢?你没有猜错,这段代码就是 commit 模板,当你 ...
- Qt学习笔记-Qtcreator的webkit和qt4.7.0的版本有关
之前下载了一个最新的是qtcreator,是通过ubuntu的是apt-get下载的.可是里面没有webkit控件.网上的网友说是最新的没有了.要用老版的,于是下载了一个2.5.2的就正常了. 用老版 ...
- HTML中,大小不确定图片的水平垂直居中
html: css: div{ width:400px;height:300px;text-align:center;font-size:0;*font-size:200px;} div:after{ ...
- 常用的linux指令
a.cd /home 进入 '/ home' 目录' b.cd .. 返回上一级目录 c.cd ../.. 返回上两级目录 d.mkdir dir1 创建一个叫做 'dir1' 的目录' e.mkdi ...