[学习笔记]状压dp
状压 \(dp\)
1、[SDOI2009]Bill的挑战
\(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数
那么方程就很明显了,每次枚举第 \(i\) 位的字母 \(alpha\) 然后 \(O(n)\) 判断就好了
时间复杂度 \(O(26Tlen2^nn)\)
\(Code\ Below:\)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int p=1e6+3;
int n,k,len,H[20],lg[1<<15],f[51][1<<15];
char s[16][51];
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
int main()
{
register int T=read(),i,j,k,t,now,l,ans;
H[0]=1;
for(i=1;i<32768;i++) lg[i]=lg[i>>1]+(i&1);
for(i=1;i<20;i++) H[i]=H[i-1]<<1;
while(T--){
n=read(),k=read();
for(i=1;i<=n;i++) scanf("%s",s[i]+1);
if(n<k){
printf("0\n");
continue;
}
len=strlen(s[1]+1);
memset(f,0,sizeof(f));
f[0][H[n]-1]=1;
for(i=1;i<=len;i++)
for(j=0;j<H[n];j++)
if(f[i-1][j]&&lg[j]>=k){
for(t=0;t<26;t++){
now=0;
for(l=1;l<=n;l++)
if((j&H[l-1])&&(s[l][i]=='?'||s[l][i]==t+'a')) now|=H[l-1];
f[i][now]=(f[i][now]+f[i-1][j])%p;
}
}
ans=0;
for(int i=0;i<H[n];i++)
if(lg[i]==k) ans=(ans+f[len][i])%p;
printf("%d\n",ans);
}
return 0;
}
2、[SDOI2009]学校食堂
状压 \(dp\) 好题!
首先 \(a\ or\ b - a\ and\ b = a\ xor\ b\)
\(f[i][j][k]\) 表示到第 \(i\) 个人状态为 \(j\) 最后一个打饭的编号为 \(i+k\) 的方案数
那么就可以转移了
if(j&1) chkmin(f[i+1][j>>1][k+7],f[i][j][k+8]);
else {
int lim=inf;
for(int l=0;l<=7;l++){
if(!(j&(1<<l))){
if(i+l>lim) break;
chkmin(lim,i+l+B[i+l]);
chkmin(f[i][j|(1<<l)][l+8],f[i][j][k+8]+(i+k?T[i+k]^T[i+l]:0));
}
}
}
\(Code\ Below:\)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
const int inf=0x3f3f3f3f;
int n,T[maxn],B[maxn],f[maxn][1<<8][16];
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void chkmin(int &a,int b){a=a<b?a:b;}
int main()
{
int Case=read();
while(Case--){
n=read();
for(int i=1;i<=n;i++)
T[i]=read(),B[i]=read();
memset(f,inf,sizeof(f));
f[1][0][7]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<256;j++)
for(int k=-8;k<=7;k++){
if(j&1) chkmin(f[i+1][j>>1][k+7],f[i][j][k+8]);
else {
int lim=inf;
for(int l=0;l<=7;l++){
if(!(j&(1<<l))){
if(i+l>lim) break;
chkmin(lim,i+l+B[i+l]);
chkmin(f[i][j|(1<<l)][l+8],f[i][j][k+8]+(i+k?T[i+k]^T[i+l]:0));
}
}
}
}
int ans=inf;
for(int i=0;i<=8;i++)
chkmin(ans,f[n+1][0][i]);
printf("%d\n",ans);
}
return 0;
}
3、[CQOI2018]解锁屏幕
\(check\) 好麻烦啊
\(Code\ Below\):
#include <bits/stdc++.h>
#define res register int
using namespace std;
const int p=1e8+7;
int n,x[20],y[20],H[20],a[20][20],dp[1<<20][20],vis[1<<20][20],ans;
int head=1,tail=0,q[(1<<20)*20*2+10];
int check(int k,int f,int j){
if(k==f||k==j) return 0;
if(x[f]==x[k]||x[f]==x[j]){
if(x[f]==x[k]&&x[f]==x[j]&&(y[f]<=y[k])==(y[k]<=y[j])) return 1;
if(y[f]==y[k]&&y[f]==y[j]&&(x[f]<=x[k])==(x[k]<=x[j])) return 1;
return 0;
}
if((x[f]<=x[k])==(x[k]<=x[j])&&(y[f]<=y[k])==(y[k]<=y[j])&&(y[f]-y[k])*(x[f]-x[j])==(y[f]-y[j])*(x[f]-x[k])) return 1;
return 0;
}
void add(res &x,const res &y){
x=x+y<p?x+y:x+y-p;
}
int main()
{
scanf("%d",&n);
res i,j,f,st;H[0]=1;
for(i=1;i<=20;i++) H[i]=H[i-1]<<1;
for(i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
for(f=0;f<n;f++)
for(j=0;j<n;j++){
if(f==j) continue;
for(i=0;i<n;i++) if(check(i,f,j)) a[f][j]+=1<<i;
}
for(i=0;i<n;i++) dp[H[i]][i]=vis[H[i]][i]=1,q[++tail]=H[i],q[++tail]=i;
while(head<=tail){
i=q[head++];f=q[head++];
st=__builtin_popcount(i);
if(st>=4) add(ans,dp[i][f]);
for(j=0;j<n;j++){
if(i&H[j]||!((a[f][j]&i)==a[f][j])) continue;
add(dp[i|H[j]][j],dp[i][f]);
if(!vis[i|H[j]][j]) vis[i|H[j]][j]=1,q[++tail]=i|H[j],q[++tail]=j;
}
}
printf("%d\n",ans);
return 0;
}
[学习笔记]状压dp的更多相关文章
- 算法笔记-状压dp
状压dp 就是把状态压缩的dp 这样还是一种暴力但相对于纯暴力还是优雅的多. 实际上dp就是经过优化的暴力罢了 首先要了解位运算 给个链接吧 [https://blog.csdn.net/u01337 ...
- 状压dp(状态压缩&&dp结合)学习笔记(持续更新)
嗯,作为一只蒟蒻,今天再次学习了状压dp(学习借鉴的博客) 但是,依旧懵逼·································· 这篇学习笔记是我个人对于状压dp的理解,如果有什么不对的 ...
- 状压dp学习笔记(紫例题集)
P3451旅游景点 Tourist Attractions 这个代码其实不算是正规题解的(因为我蒟蒻)是在我们的hzoj上内存限制324MIB情况下过掉的,而且经过研究感觉不太能用滚动数组,所以那这个 ...
- 状压DP学习笔记
有的时候,我们会发现一些问题的状态很难直接用几个数表示,这个时候我们就会用到状压dp啦~~. 状压就是状态压缩,就是讲原本复杂难以描述的状态用一个数或者几个数来表示qwq.状态压缩是一个很常用的技巧, ...
- MMM 状压dp学习记
状压dp学习记 by scmmm 开始日期 2019/7/17 前言 状压dp感觉很好理解(本质接近于爆搜但是又有广搜的感觉),综合了dp的高效性(至少比dfs,bfs优),又能解决普通dp难搞定的问 ...
- 状压DP复习笔记
前言 复习笔记第4篇.CSP RP++. 引用部分为总结性内容. 0--P1433 吃奶酪 题目链接 luogu 题意 房间里放着 \(n\) 块奶酪,要把它们都吃掉,问至少要跑多少距离?一开始在 \ ...
- 「算法笔记」状压 DP
一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...
- CH0103最短Hamilton路径 & poj2288 Islands and Brigdes【状压DP】
虐狗宝典学习笔记: 取出整数\(n\)在二进制表示下的第\(k\)位 \((n >> ...
- 有关状压DP
[以下内容仅为本人在学习中的所感所想,本人水平有限目前尚处学习阶段,如有错误及不妥之处还请各位大佬指正,请谅解,谢谢!] 引言 动态规划虽然已经是对暴力算法的优化,但在某些比较特别的情况下,可以通过一 ...
随机推荐
- SpringMVC学习八 @ResponseBody注解
(一)在方法上只有@RequestMapping 时,无论方法返回值是什么认为需要跳转,代码实例如下 @RequestMapping("demo10") public People ...
- Alpha 冲刺 (1/10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作,对多个目标检测及文字识别模型进行评估.实验,选取较 ...
- WPF禁止拖拽窗口到边缘自动最大化
近期有个需求,可以通过拖拽改变窗口大小,但是不允许窗口最大化.最小化.拖到边缘的时候也不能自动最大化. 要想禁止拖拽窗口到边缘自动最大化,只要改注册表即可,但是系统所有应用都会被禁止. 1.运行reg ...
- Firefox,chrome,IE上传图片预览
首先判断IE或是Firefox,chrome.本文只测试了IE8中和Firefox,chrome是不一样的. 判断是否IE: if(-[1,]){//判断浏览器不是IE //alert((-[1 ...
- 6. Uniforms in American's Eyes 美国人眼里的制服
6. Uniforms in American's Eyes 美国人眼里的制服 (1) Americans are proud of their variety and individuality,y ...
- VC播放mp3的方法
1.使用msi库 #include <mmsystem.h> #pragma comment(lib,"winmm.lib") ....... //打开文件 MCI_O ...
- win7 C环境搭建
1 http://jingyan.baidu.com/article/14bd256e4cb86ebb6d261287.html 2 http://jingyan.baidu.com/arti ...
- CodeForces 235E Number Challenge (莫比乌斯反演)
题意:求,其中d(x) 表示 x 的约数个数. 析:其实是一个公式题,要知道一个结论 知道这个结论就好办了. 然后就可以解决这个问题了,优化就是记忆化gcd. 代码如下: #pragma commen ...
- Web结构组件
一.Web结构组件 1.代理 位于客户端和服务器之间的HTTP实体,接收客户端的所有HTTP请求,并将这些请求转发给HTTP服务器. 2.缓存 HTTP的仓库,使常用的页面的副本可以保存在离客户端更近 ...
- 20169207《Linux内核原理与分析》第十周作业
这周除了阅读学习教材「Linux内核设计与实现 (Linux Kernel Development)」第教材第15,16章外.我们还需要接着完成学习MOOC「Linux内核分析」第八讲「Linux系统 ...