div2的F题,只想到了一个复杂度略高的dp,T了几次,后来加了剪枝减掉一些无用的状态终于过了。。

题意:

一个n*m的矩阵 (n<=5,m<=20),对格子进行黑白染色,已经给出了每行每列黑色联通块的个数,要求输出一组答案,满足有解。

思路:

首先发现n只有5,考虑按列处理,每列总共有2^5=32种状态;又发现对于给出的联通块个数,最坏情况是当联通块个数等于1或者2的时候有15种情况

比直接二进制处理快了一倍。所以我们可以预先处理出联通块个数为0~3时对于的二进制状态;

找到了列的基本状态,现在来考虑转移:

首先在转移时应该满足每行的黑色联通块个数,所以每行当前的联通块个数是需要保存的,由于m<=20所以每行最多有0~10这11种情况,考虑到5行就总共有11^5种状态

所以总共的状态数即为 20*15*11^5=48315300 由于cf的机器很强大这个状态数基本算是可以接受了

转移时处理如下:对于每一行如果上一列为0且当前列为1,则联通块数目+1,其他情况联通块数目不变。

这样我们就可以解决整个dp的过程了,由于题目要求输出染色方案,我们就需要记录每一个状态的前驱,最后通过前驱获得答案

但是直接交上去还是会T的,这里有两个剪枝可以使用

1.在转移过程中如果当前行的联通块个数已经大于题目给的个数,直接把这个状态减掉

2.在转移过程中如果当前行的联通块个数在剩下的列里怎么取(最好情况为一黑一白这样染)都不可能达到题目给的个数,把这个状态减掉

最后终于ac了!

代码:

 #include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<ctype.h>
#include<vector>
using namespace std;
#define MAXN 10000
bool dp[][][];
int pret[];
int x[];
int y[];
int p[];
int ans[];
int v[][];
int nn[];
int n,m;
int fun(int s)
{
int res=;
int pre=;
for(int i=; i<n; i++)
{
if((s&(<<i))&&pre==)
{
res++;
}
pre=(bool)(s&(<<i));
}
return res;
}
inline int get(int s,int i)
{
return (s%p[i+])/p[i];
}
int fuck(int s,int pre,int now,int pos)
{
int res=;
for(int i=; i<n; i++)
{
int tmp=(get(s,i)+((!(pre&(<<i)))&&(now&(<<i))));
if(tmp>x[i])
return -;
if(tmp+(m-pos)/<x[i])
return -;
res+=tmp*p[i];
}
return res;
}
inline int make(int i,int j,int s)
{
return s+j*+i**;
} inline int getj(int t)
{
return (t%(*))/;
} char s[][];
int main()
{
cin>>n>>m;
p[]=;
for(int i=; i<=; i++)
{
p[i]=p[i-]*;
}
for(int i=; i<(<<n); i++)
{
int tmp=fun(i);
v[tmp][nn[tmp]++]=i;
}
for(int i=; i<n; i++)
{
cin>>x[i];
}
for(int i=; i<m; i++)
{
cin>>y[i];
}
for(int i=; i<nn[y[]]; i++)
{
dp[][i][fuck(,,v[y[]][i],)]=;
}
int now,pre,st;
for(int i=; i<m; i++)
{
for(int j=; j<nn[y[i-]]; j++)
{
for(int s=; s<; s++)
{
if(dp[i-][j][s])
{
for(int k=; k<nn[y[i]]; k++)
{
st=fuck(s,v[y[i-]][j],v[y[i]][k],i);
if(st<)
continue;
dp[i][k][st]=;
pret[make(i,k,st)]=make(i-,j,s);
}
}
}
}
}
now=;
for(int i=;i<n;i++)
{
now+=x[i]*p[i];
}
int j=-;
for(int i=;i<nn[y[m-]];i++)
{
if(dp[m-][i][now])
{
j=i;
break;
}
} now=make(m-,j,now);
for(int i=m-;i>=;i--)
{
ans[i]=v[y[i]][getj(now)];
now=pret[now];
}
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
s[i][j]=((ans[j])&(<<i))?'*':'.';
}
}
for(int i=;i<n;i++)
{
puts(s[i]);
}
return ;
}

cf298F:状压dp+剪枝的更多相关文章

  1. Atcoder Typical DP Contest S - マス目(状压 dp+剪枝)

    洛谷题面传送门 介绍一个不太主流的.非常暴力的做法( 首先注意到 \(n\) 非常小,\(m\) 比较大,因此显然以列为阶段,对行的状态进行状压.因此我们可以非常自然地想到一个非常 trivial 的 ...

  2. hdu 4739 状压DP

    这里有状态压缩DP的好博文 题目:题目比较神,自己看题目吧 分析: 大概有两种思路: 1.dfs,判断正方形的话可以通过枚举对角线,大概每次减少4个三角形,加上一些小剪枝的话可以过. 2.状压DP,先 ...

  3. 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)

    洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...

  4. NOIp2017D2T2(luogu3959) 宝藏 (状压dp)

    时隔多年终于把这道题锅过了 数据范围显然用搜索剪枝状压dp. 可以记还有哪些点没到(或者已到了哪些点).我们最深已到的是哪些点.这些点的深度是多少,然后一层一层地往下推. 但其实是没必要记最深的那一层 ...

  5. dp,状压dp等 一些总结

    也就作业几题而已,分析一下提醒 最重要的就是,记住,没用的状态无论怎么转移最后都会是没用的状态,所以每次转移以后的有值的状态都是有用的状态. 几种思考方向: 第一种:枚举当前的状态,转移成另外一个状态 ...

  6. NOIP2016愤怒的小鸟 [状压dp]

    愤怒的小鸟 题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟, ...

  7. 【NOIP2017】宝藏 题解(状压DP)

    题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nnn 个深埋在地下的宝藏屋, 也给出了这 nnn 个宝藏屋之间可供开发的m mm 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中 ...

  8. T2988 删除数字【状压Dp+前缀和优化】

    Online Judge:从Topcoder搬过来,具体哪一题不清楚 Label:状压Dp+前缀和优化 题目描述 给定两个数A和N,形成一个长度为N+1的序列,(A,A+1,A+2,...,A+N-1 ...

  9. 「状压DP」「暴力搜索」排列perm

    「状压DP」「暴力搜索」排列 题目描述: 题目描述 给一个数字串 s 和正整数 d, 统计 sss 有多少种不同的排列能被 d 整除(可以有前导 0).例如 123434 有 90 种排列能被 2 整 ...

随机推荐

  1. Ext.Panel的主要功能

    介绍面板组件的主要配置项及经常用法,这些配置项及方法将在后面的演示样例中用到,能够把这部分内容作为兴许章节的铺垫,进行高速的浏览,Ext.Panel主要配置项目如表5-1所看到的. 表5-1  Ext ...

  2. Robotium -- 使用JunitReport导出测试报告

    使用Robotium进行测试的时候,要想可以导出明了的测试结果,可以使用junitreport来实现 junit-report下载地址:https://github.com/jsankey/andro ...

  3. HTML编辑器UEditor的简单使用

    參考自:http://ueditor.baidu.com/website/document.html 关于HTML编辑器,试过FCKeditor,升级版的CKeditor,还有TinyMCE,近期在尝 ...

  4. ·数据库基本内容回顾-day16.06.30

    一. 模式的定义和删除  ---创建了一个模式,就创建了一个数据库命名空间,一个框架.cascade.restrict create schema<模式名> authorization & ...

  5. ERROR<53761> - Plugins - conn=-1 op=-1 msgId=-1 - Connection Bind through PTA failed (91). Retrying...

    LDAP6.3在DSCC控制台启动实例完成,但是操作状态显示“意外错误”,查看日志如下: 04/May/2016:21:10:39 +0800] - Sun-Java(tm)-System-Direc ...

  6. python 整型--《Python 3程序开发指南》笔记

    参考:<Python 3程序开发指南> 整数转换函数: bin(i) 返回整数i的二进制表示(字符串) hex(i) 返回i的十六进制表示(字符串) int(x) 将x转换为整数,失败产生 ...

  7. 图片样式 scaleType 属性

    ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType),不同值的意义区别:

  8. hdu 4772

    题意:给你两个矩阵,一个矩阵旋转90度,180度,270度, 然后和另外一个矩阵进行比较,如果对应值相同,则加一,最后得出最大的值 题目没什么难度....主要是纪念下....貌似这一题是当时比赛前一个 ...

  9. 打jar包的方法

    打jar包的方法是什么? java打jar包,引用其他.jar文件 java项目打jar包 将java源码打成jar包 maven打jar例子 打war包的方法是什么? Eclipse->项目右 ...

  10. 实现SQLServer数据库转成MYSQL数据库

    1.首先需要下载安装工具Navicat Premium. 2.注意:将数据库移至本地SQLServer,我试过直接在局域网上其他SQLServer服务器上想转到本地Mysql好像有问题,想将远程数据库 ...