cf298F:状压dp+剪枝
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+剪枝的更多相关文章
- Atcoder Typical DP Contest S - マス目(状压 dp+剪枝)
洛谷题面传送门 介绍一个不太主流的.非常暴力的做法( 首先注意到 \(n\) 非常小,\(m\) 比较大,因此显然以列为阶段,对行的状态进行状压.因此我们可以非常自然地想到一个非常 trivial 的 ...
- hdu 4739 状压DP
这里有状态压缩DP的好博文 题目:题目比较神,自己看题目吧 分析: 大概有两种思路: 1.dfs,判断正方形的话可以通过枚举对角线,大概每次减少4个三角形,加上一些小剪枝的话可以过. 2.状压DP,先 ...
- 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)
洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...
- NOIp2017D2T2(luogu3959) 宝藏 (状压dp)
时隔多年终于把这道题锅过了 数据范围显然用搜索剪枝状压dp. 可以记还有哪些点没到(或者已到了哪些点).我们最深已到的是哪些点.这些点的深度是多少,然后一层一层地往下推. 但其实是没必要记最深的那一层 ...
- dp,状压dp等 一些总结
也就作业几题而已,分析一下提醒 最重要的就是,记住,没用的状态无论怎么转移最后都会是没用的状态,所以每次转移以后的有值的状态都是有用的状态. 几种思考方向: 第一种:枚举当前的状态,转移成另外一个状态 ...
- NOIP2016愤怒的小鸟 [状压dp]
愤怒的小鸟 题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟, ...
- 【NOIP2017】宝藏 题解(状压DP)
题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nnn 个深埋在地下的宝藏屋, 也给出了这 nnn 个宝藏屋之间可供开发的m mm 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中 ...
- T2988 删除数字【状压Dp+前缀和优化】
Online Judge:从Topcoder搬过来,具体哪一题不清楚 Label:状压Dp+前缀和优化 题目描述 给定两个数A和N,形成一个长度为N+1的序列,(A,A+1,A+2,...,A+N-1 ...
- 「状压DP」「暴力搜索」排列perm
「状压DP」「暴力搜索」排列 题目描述: 题目描述 给一个数字串 s 和正整数 d, 统计 sss 有多少种不同的排列能被 d 整除(可以有前导 0).例如 123434 有 90 种排列能被 2 整 ...
随机推荐
- Ext.Panel的主要功能
介绍面板组件的主要配置项及经常用法,这些配置项及方法将在后面的演示样例中用到,能够把这部分内容作为兴许章节的铺垫,进行高速的浏览,Ext.Panel主要配置项目如表5-1所看到的. 表5-1 Ext ...
- Robotium -- 使用JunitReport导出测试报告
使用Robotium进行测试的时候,要想可以导出明了的测试结果,可以使用junitreport来实现 junit-report下载地址:https://github.com/jsankey/andro ...
- HTML编辑器UEditor的简单使用
參考自:http://ueditor.baidu.com/website/document.html 关于HTML编辑器,试过FCKeditor,升级版的CKeditor,还有TinyMCE,近期在尝 ...
- ·数据库基本内容回顾-day16.06.30
一. 模式的定义和删除 ---创建了一个模式,就创建了一个数据库命名空间,一个框架.cascade.restrict create schema<模式名> authorization & ...
- 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 ...
- python 整型--《Python 3程序开发指南》笔记
参考:<Python 3程序开发指南> 整数转换函数: bin(i) 返回整数i的二进制表示(字符串) hex(i) 返回i的十六进制表示(字符串) int(x) 将x转换为整数,失败产生 ...
- 图片样式 scaleType 属性
ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType),不同值的意义区别:
- hdu 4772
题意:给你两个矩阵,一个矩阵旋转90度,180度,270度, 然后和另外一个矩阵进行比较,如果对应值相同,则加一,最后得出最大的值 题目没什么难度....主要是纪念下....貌似这一题是当时比赛前一个 ...
- 打jar包的方法
打jar包的方法是什么? java打jar包,引用其他.jar文件 java项目打jar包 将java源码打成jar包 maven打jar例子 打war包的方法是什么? Eclipse->项目右 ...
- 实现SQLServer数据库转成MYSQL数据库
1.首先需要下载安装工具Navicat Premium. 2.注意:将数据库移至本地SQLServer,我试过直接在局域网上其他SQLServer服务器上想转到本地Mysql好像有问题,想将远程数据库 ...