SGU 132. Another Chocolate Maniac 状压dp 难度:1
132. Another Chocolate Maniac
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
Bob really LOVES chocolate. He thinks he never gets enough. Imagine his joy when his parents told him that they would buy him many rectangular chocolate pieces for his birthday. A piece of chocolate is a 2x1 or1x2 rectangle. Bob's parents also bought him a nice birthday cake, which can be imagined as a matrix having M rows and N columns. Some positions on the cake are occupied by candles, the others are empty. Bob's parents asked their son to place as many chocolate pieces as he can on the empty squares on the cake, in such a manner that no two chocolate pieces overlap. However, he would like to keep the chocolate pieces to himself. That's why, he wants to place only a minimal amount of them on the cake and keep the rest. In order not to make Mon and Dad suspicious, Bob wants to place the chocolate pieces in such a way, that no other piece may be placed on the cake (that is, there won't exist any two adjacent empty squares). Find the minimal number of pieces which need to be placed on the cake, so that they do not overlap and no extra piece may be added.
Input
The first line of the input contains 2 integers: M (1<=M<=70) and N (1<=N<=7). Next, M lines will follow, each of them containing N characters, describing the cake. The character on row i and column j of the cake may be either a '*' (ASCII code 42), representing a candle, or a '.' (ASCII code 46), representing an empty square.
Output
You should output one integer: the minimal amount of pieces of chocolate which need to be placed on the cake.
Sample Input
5 5
.*..*
*....
..**.
**.*.
.**..
Sample Output
4
简单的状态压缩,注意不填充这个格子的时候,可以填充左边的两个,下和右下,下和左下即可,然后就是如果恰有一对上下都没有填充,可以试试能否填充下和下下
#include <cstring>
#include <algorithm>
using namespace std;
#define bin(bit) (1<<(bit))
#define spb(x,bit) ((x)&(1<<(bit)))
const int inf=0x3f3f3f3f;
char maz[75][10];
int dp[2][1<<8][1<<8]; int init[75];
int n,m;
int row,nrow,len;
int inver(int ind){//初始状态转成数字
int ans=0;
int base=1;
for(int i=0;i<m;i++){
if(maz[ind][i]=='*'){
ans+=base;
}
base<<=1;
}
return ans;
}
bool contain(int nowline,int nxtline,int nnxtline){//如果恰好该状态有格子在某个格和下一个格都没填充,检查能否填充下下格,当然,下下格状态就是下下行对应的初始状态
int base=1;
row=nxtline;nrow =nnxtline;len=0;
for(int i=0;i<m;i++){
if((nowline&base)==0&&(nxtline&base)==0){
if((nnxtline&base)!=0)return false;
else {nrow|=base;row|=base;len++;}
}
base<<=1;
}
return true;
}
bool judge(int nowline,int nxtline){//判断这一行相对下一行是否都符合规范(没有格不合题意)
for(int i=0;i<m;i++){
if(spb(nowline,i)==0){
if(spb(nxtline,i)==0){return false;}
if(i<m-1&&spb(nowline,i+1)==0)return false;
}
}
return true;
}
bool judge(int nowline){//判断这一行是否符合规范
for(int i=0;i<m;i++){
if(spb(nowline,i)==0){
if(i<m-1&&spb(nowline,i+1)==0)return false;
}
}
return true;
}
void update(int cnt,int stj,int stk){//用这个状态更新同行的其它状态
for(int i=0;i<m;i++){
if(spb(stj,i)==0){
/*
TT
*/
if(i<m-1&&spb(stj,i+1)==0){
dp[cnt][stj|bin(i+1)|bin(i)][stk]=min( dp[cnt][stj|bin(i+1)|bin(i)][stk],dp[cnt][stj][stk]+1);
} /* ATT
*/
if(i<m-2&&spb(stj,i+2)==0&&spb(stj,i+1)==0){
dp[cnt][stj|bin(i+2)|bin(i+1)][stk]=min( dp[cnt][stj|bin(i+2)|bin(i+1)][stk],dp[cnt][stj][stk]+1);
}
/*
T
T
*/
if(spb(stk,i)==0){
dp[cnt][stj|bin(i)][stk|bin(i)]=min( dp[cnt][stj|bin(i)][stk|bin(i)],dp[cnt][stj][stk]+1);
}
/*
A
TT
*/
if(i<m-1&&spb(stk,i+1)==0&&spb(stk,i)==0){
dp[cnt][stj][stk|bin(i+1)|bin(i)]=min( dp[cnt][stj][stk|bin(i+1)|bin(i)],dp[cnt][stj][stk]+1);
}
/*
A
TT
*/
if(i&&spb(stk,i)==0&&spb(stk,i-1)==0){
dp[cnt][stj][stk|bin(i)|bin(i-1)]=min( dp[cnt][stj][stk|bin(i)|bin(i-1)],dp[cnt][stj][stk]+1);
}
}
}
}
int main(){
memset(dp[0],0x3f,sizeof(dp[0]));
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){//初始化
scanf("%s",maz[i]);
init[i]=inver(i);
}
dp[0][bin(m)-1][init[0]]=0;
init[n]=0;
init [n+1]=0;
int cnt=0; for(int i=0;i<=n;i++){
memset(dp[cnt^1],0x3f,sizeof(dp[0]));
for(int j=0;j<bin(m);j++){//行内dp
for(int k=0;k<bin(m);k++){
if(dp[cnt][j][k]!=inf){
update(cnt,j,k);
}
}
}
// printdp(i,true);
if(i==n)continue;//如果恰好到了最后一行了,就不需要行间转移
for(int j=0;j<bin(m);j++){//行间转移
if(!judge(j))continue;
for(int k=0;k<bin(m);k++){
if(dp[cnt][j][k]==inf)continue;
if(judge(j,k)){//如果已经满足题意
dp[cnt^1][k][init[i+1]]=min(dp[cnt^1][k][init[i+1]],dp[cnt][j][k]);
}
else if(contain(j,k,init[i+1])){//否则试试染下下
dp[cnt^1][row][nrow]=min(dp[cnt^1][row][nrow],dp[cnt][j][k]+len);
}
}
}
// printdp(i,false);
cnt^=1;
}
int ans=inf;
for(int j=0;j<bin(m);j++){
if(!judge(j))continue;
ans=min(ans,dp[cnt][j][0]);
}
printf("%d\n",ans);
return 0;
}
SGU 132. Another Chocolate Maniac 状压dp 难度:1的更多相关文章
- SGU 132 Another Chocolate Maniac 状态压缩DP
感觉不是很好写的一道状态压缩. dp[i][j][k]表示第 i 行状态为k,第i - 1行状态为 j,具体细节见代码. 内存卡的很死,要用滚动数组. 还有一个比较坑爹的地方是它在输入蛋糕的时候中间可 ...
- SGU 223 Little Kings(状压DP)
Description 用字符矩阵来表示一个8x8的棋盘,'.'表示是空格,'P'表示人质,'K'表示骑士.每一步,骑士可以移动到他周围的8个方格中的任意一格.如果你移动到的格子中有人质(即'P'), ...
- SGU 132.Another Chocolate Maniac
时间限制:0.25s 空间限制:4M 题目: Bob非常喜欢巧克力,吃再多也觉得不够.当他的父母告诉他将要买很多矩形巧克力片为他庆祝生日时,他的喜悦是能被理解的.巧克力都是 2x1 或 1x2 的矩形 ...
- SGU 223 little kings BSOJ2772 状压DP
1896 [SCOI2005]互不侵犯King [问题描述]在n*n(1<=n<=10)的棋盘上放k(0<=k<=n*n)个国王(可攻击相邻的8 个格子),求使它们无法互相攻击 ...
- SGU 131. Hardwood floor 状压dp 难度:2
131. Hardwood floor time limit per test: 0.25 sec. memory limit per test: 4096 KB The banquet hall o ...
- 【模拟8.11】星空(差分转化,状压DP,最短路)
一道很好的题,综合很多知识点. 首先复习差分: 将原来的每个点a[i]转化为b[i]=a[i]^a[i+1],(如果是求和形式就是b[i]=a[i+1]-a[i]) 我们发现这样的方便在于我 ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
随机推荐
- Python开发【Django】:Admin配置管理
Admin创建登录用户 数据库结构表: from django.db import models # Create your models here. class UserProfile(models ...
- 使用linuxbridge + vlan网络模式
#openstack pike 使用 linuxbridge + vlan openstack pike 集群高可用 安装部署 汇总 http://www.cnblogs.com/elvi/p/76 ...
- 洛谷P1373 小a和uim之大逃离 dp
正解:dp 解题报告: 传送门! 同样是看到列表发的题解就想着跟着做下dp的题目趴 然后发现还挺难的,,,反正我只大概想到怎么转移但是初始化什么的都不会TT 所以还是大概说下QAQ 首先可以想到设f[ ...
- SQL基础--查询之二--连接查询
SQL基础--查询之二--连接查询
- android ListView几个有用的属性
1. stackFromBottom,设置为ture你做好的列表就会显示你列表的最下面 2. transciptMode,通过设置的控件transcriptMode属性可以将Android平台的控件( ...
- 【Python】【爬虫】如何学习Python爬虫?
如何学习Python爬虫[入门篇]? 路人甲 1 年前 想写这么一篇文章,但是知乎社区爬虫大神很多,光是整理他们的答案就够我这篇文章的内容了.对于我个人来说我更喜欢那种非常实用的教程,这种教程对于想直 ...
- Java面试人事篇(二)
1.请你自我介绍一下你自己? 回答提示:一般人回答这个问题过于平常,只说姓名.年龄.爱好.工作经验,这些在简历上都有.其实,企业最希望知道的是求职者能否胜任工作,包括:最强的技能.最深入研究的知识领域 ...
- [py]python中__new__作用
元类metaclass 使劲搞,但是没搞清楚__new__的作用 了解Python元类 Python进阶:一步步理解Python中的元类metaclass Python中的__new__和__init ...
- 搭建markdown图床-腾讯云COS
背景介绍 书写markdown笔记时,如何处理图片,实在是有些棘手的问题.每一张图都保存在当前文件夹? 每张图都自己重命名?每次上传到cnblogs博客都需要一张一张拖动?markdown已经非常成功 ...
- Java用数据结构解决实现问题之数学问题
有趣的整数: 完数:如果一个数字恰好等于他的因子之和,就叫做完数,需求是求出10000以内的所有的完数. 解法:1.用n去除以1-n之间的所有的整数,将能整除的被除数保存到一个数组中,作为n的一个因子 ...