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 整 ...
随机推荐
- [React] Radium: Updating Button Styles via Props
In a CSS library like Bootstrap we can set a button's style to be "primary" or "secon ...
- 转 [教程] Unity3D中角色的动画脚本的编写(二)
在上一篇,我们介绍了有关Animation这个类中的部分方法,我后来想了想,这么介绍也不是个办法(其实有些方法我自己也没用过),该介绍点实际的东西了,毕竟我们是要做东西出来的.那好 ...
- UML解惑:图说UML中的六大关系--转
UML定义的关系主要有六种:依赖.类属.关联.实现.聚合和组合.这些类间关系的理解和使用是掌握和应用UML的关键,而也就是这几种关系,往往会让初学者迷惑.这里给出这六种主要UML关系的说明和类图描述, ...
- Embedded tomcat 7 servlet 3.0 annotations not working--转
Question: I have a stripped down test project which contains a Servlet version 3.0, declared with an ...
- java设计模式---享元模式
享元模式 顾名思义:共享元对象.如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用创建新的对象. 享元模式是为数不多的.只为提升系统性能而生的设计模式.它的主要作用就 ...
- 编程小计——消除Graphics图像边缘颜色不纯(抗锯齿)
在很多时候,我们都要绘制纯色的图片,而用Graphics生成的往往是不纯的,尤其是绘制文字时.比如说绘制纯红色文字,往往R达不到255. C#中默认抗锯齿,给人看起来柔和:但是我们现实中往往用到锯齿. ...
- 用MS自带的VS构建joint语句
在其中一个表上,右键,选择"New Query",弹出"Add Table"对话框,将待joint的两个表Add,并选择相应字段,则会自动构建joint语句,其 ...
- office - 连接字符串.
Microsoft ACE OLEDB 12.0 Connect to Excel 2007 (and later) files with the Xlsx file extension. That ...
- 关于Adobe Flash 11.3 引起的火狐使用问题
Adobe Flash 更新到11.3之后,为火狐引入Flash沙盒安全模式,但同时,又造成了部分兼容性问题,导致 Windows vista及 Windows 7上部分火狐崩溃,并致使一些使用Fla ...
- Objective-C 笔记一(HelloWorld)
作为一个果粉And程序员,奔着对OC浓厚的兴趣,开始学习IOS.并以后也想从事IOS开发工作.并将自己的学习记录下来,俗话说的好,不会总结的程序猿,不是好程序员! Xcode可以在AppStore里下 ...