状压 \(dp\)


1、[SDOI2009]Bill的挑战

\(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数

那么方程就很明显了,每次枚举第 \(i\) 位的字母 \(alpha\) 然后 \(O(n)\) 判断就好了

时间复杂度 \(O(26Tlen2^nn)\)

\(Code\ Below:\)

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. const int p=1e6+3;
  5. int n,k,len,H[20],lg[1<<15],f[51][1<<15];
  6. char s[16][51];
  7. inline int read(){
  8. register int x=0,f=1;char ch=getchar();
  9. while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
  10. while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
  11. return (f==1)?x:-x;
  12. }
  13. int main()
  14. {
  15. register int T=read(),i,j,k,t,now,l,ans;
  16. H[0]=1;
  17. for(i=1;i<32768;i++) lg[i]=lg[i>>1]+(i&1);
  18. for(i=1;i<20;i++) H[i]=H[i-1]<<1;
  19. while(T--){
  20. n=read(),k=read();
  21. for(i=1;i<=n;i++) scanf("%s",s[i]+1);
  22. if(n<k){
  23. printf("0\n");
  24. continue;
  25. }
  26. len=strlen(s[1]+1);
  27. memset(f,0,sizeof(f));
  28. f[0][H[n]-1]=1;
  29. for(i=1;i<=len;i++)
  30. for(j=0;j<H[n];j++)
  31. if(f[i-1][j]&&lg[j]>=k){
  32. for(t=0;t<26;t++){
  33. now=0;
  34. for(l=1;l<=n;l++)
  35. if((j&H[l-1])&&(s[l][i]=='?'||s[l][i]==t+'a')) now|=H[l-1];
  36. f[i][now]=(f[i][now]+f[i-1][j])%p;
  37. }
  38. }
  39. ans=0;
  40. for(int i=0;i<H[n];i++)
  41. if(lg[i]==k) ans=(ans+f[len][i])%p;
  42. printf("%d\n",ans);
  43. }
  44. return 0;
  45. }

2、[SDOI2009]学校食堂

状压 \(dp\) 好题!

首先 \(a\ or\ b - a\ and\ b = a\ xor\ b\)

\(f[i][j][k]\) 表示到第 \(i\) 个人状态为 \(j\) 最后一个打饭的编号为 \(i+k\) 的方案数

那么就可以转移了

  1. if(j&1) chkmin(f[i+1][j>>1][k+7],f[i][j][k+8]);
  2. else {
  3. int lim=inf;
  4. for(int l=0;l<=7;l++){
  5. if(!(j&(1<<l))){
  6. if(i+l>lim) break;
  7. chkmin(lim,i+l+B[i+l]);
  8. chkmin(f[i][j|(1<<l)][l+8],f[i][j][k+8]+(i+k?T[i+k]^T[i+l]:0));
  9. }
  10. }
  11. }

\(Code\ Below:\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=1000+10;
  4. const int inf=0x3f3f3f3f;
  5. int n,T[maxn],B[maxn],f[maxn][1<<8][16];
  6. inline int read(){
  7. register int x=0,f=1;char ch=getchar();
  8. while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
  9. while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
  10. return (f==1)?x:-x;
  11. }
  12. inline void chkmin(int &a,int b){a=a<b?a:b;}
  13. int main()
  14. {
  15. int Case=read();
  16. while(Case--){
  17. n=read();
  18. for(int i=1;i<=n;i++)
  19. T[i]=read(),B[i]=read();
  20. memset(f,inf,sizeof(f));
  21. f[1][0][7]=0;
  22. for(int i=1;i<=n;i++)
  23. for(int j=0;j<256;j++)
  24. for(int k=-8;k<=7;k++){
  25. if(j&1) chkmin(f[i+1][j>>1][k+7],f[i][j][k+8]);
  26. else {
  27. int lim=inf;
  28. for(int l=0;l<=7;l++){
  29. if(!(j&(1<<l))){
  30. if(i+l>lim) break;
  31. chkmin(lim,i+l+B[i+l]);
  32. chkmin(f[i][j|(1<<l)][l+8],f[i][j][k+8]+(i+k?T[i+k]^T[i+l]:0));
  33. }
  34. }
  35. }
  36. }
  37. int ans=inf;
  38. for(int i=0;i<=8;i++)
  39. chkmin(ans,f[n+1][0][i]);
  40. printf("%d\n",ans);
  41. }
  42. return 0;
  43. }

3、[CQOI2018]解锁屏幕

\(check\) 好麻烦啊

\(Code\ Below\):

  1. #include <bits/stdc++.h>
  2. #define res register int
  3. using namespace std;
  4. const int p=1e8+7;
  5. int n,x[20],y[20],H[20],a[20][20],dp[1<<20][20],vis[1<<20][20],ans;
  6. int head=1,tail=0,q[(1<<20)*20*2+10];
  7. int check(int k,int f,int j){
  8. if(k==f||k==j) return 0;
  9. if(x[f]==x[k]||x[f]==x[j]){
  10. if(x[f]==x[k]&&x[f]==x[j]&&(y[f]<=y[k])==(y[k]<=y[j])) return 1;
  11. if(y[f]==y[k]&&y[f]==y[j]&&(x[f]<=x[k])==(x[k]<=x[j])) return 1;
  12. return 0;
  13. }
  14. 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;
  15. return 0;
  16. }
  17. void add(res &x,const res &y){
  18. x=x+y<p?x+y:x+y-p;
  19. }
  20. int main()
  21. {
  22. scanf("%d",&n);
  23. res i,j,f,st;H[0]=1;
  24. for(i=1;i<=20;i++) H[i]=H[i-1]<<1;
  25. for(i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
  26. for(f=0;f<n;f++)
  27. for(j=0;j<n;j++){
  28. if(f==j) continue;
  29. for(i=0;i<n;i++) if(check(i,f,j)) a[f][j]+=1<<i;
  30. }
  31. for(i=0;i<n;i++) dp[H[i]][i]=vis[H[i]][i]=1,q[++tail]=H[i],q[++tail]=i;
  32. while(head<=tail){
  33. i=q[head++];f=q[head++];
  34. st=__builtin_popcount(i);
  35. if(st>=4) add(ans,dp[i][f]);
  36. for(j=0;j<n;j++){
  37. if(i&H[j]||!((a[f][j]&i)==a[f][j])) continue;
  38. add(dp[i|H[j]][j],dp[i][f]);
  39. if(!vis[i|H[j]][j]) vis[i|H[j]][j]=1,q[++tail]=i|H[j],q[++tail]=j;
  40. }
  41. }
  42. printf("%d\n",ans);
  43. return 0;
  44. }

[学习笔记]状压dp的更多相关文章

  1. 算法笔记-状压dp

    状压dp 就是把状态压缩的dp 这样还是一种暴力但相对于纯暴力还是优雅的多. 实际上dp就是经过优化的暴力罢了 首先要了解位运算 给个链接吧 [https://blog.csdn.net/u01337 ...

  2. 状压dp(状态压缩&&dp结合)学习笔记(持续更新)

    嗯,作为一只蒟蒻,今天再次学习了状压dp(学习借鉴的博客) 但是,依旧懵逼·································· 这篇学习笔记是我个人对于状压dp的理解,如果有什么不对的 ...

  3. 状压dp学习笔记(紫例题集)

    P3451旅游景点 Tourist Attractions 这个代码其实不算是正规题解的(因为我蒟蒻)是在我们的hzoj上内存限制324MIB情况下过掉的,而且经过研究感觉不太能用滚动数组,所以那这个 ...

  4. 状压DP学习笔记

    有的时候,我们会发现一些问题的状态很难直接用几个数表示,这个时候我们就会用到状压dp啦~~. 状压就是状态压缩,就是讲原本复杂难以描述的状态用一个数或者几个数来表示qwq.状态压缩是一个很常用的技巧, ...

  5. MMM 状压dp学习记

    状压dp学习记 by scmmm 开始日期 2019/7/17 前言 状压dp感觉很好理解(本质接近于爆搜但是又有广搜的感觉),综合了dp的高效性(至少比dfs,bfs优),又能解决普通dp难搞定的问 ...

  6. 状压DP复习笔记

    前言 复习笔记第4篇.CSP RP++. 引用部分为总结性内容. 0--P1433 吃奶酪 题目链接 luogu 题意 房间里放着 \(n\) 块奶酪,要把它们都吃掉,问至少要跑多少距离?一开始在 \ ...

  7. 「算法笔记」状压 DP

    一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...

  8. CH0103最短Hamilton路径 & poj2288 Islands and Brigdes【状压DP】

    虐狗宝典学习笔记: 取出整数\(n\)在二进制表示下的第\(k\)位                                                    \((n >> ...

  9. 有关状压DP

    [以下内容仅为本人在学习中的所感所想,本人水平有限目前尚处学习阶段,如有错误及不妥之处还请各位大佬指正,请谅解,谢谢!] 引言 动态规划虽然已经是对暴力算法的优化,但在某些比较特别的情况下,可以通过一 ...

随机推荐

  1. Python 语法糖装饰器的应用

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  2. 关于ueditor 在struts2 中 上传图片 ,未找到上传文件 问题的解决方法

    问题原因: ueditor 上传图片需请求imageUp.jsp文件,struts2 自带的拦截器(/*)把所有请求的文件都做了处理,所以导致无法上传图片. 解决方法: 方法一:自定义拦截器,让它在请 ...

  3. 进度条的制作unity

    不说了直接上代码: LoadingPanel: using UnityEngine;using System.Collections;using UnityEngine.UI;using UnityE ...

  4. 2018.11.08 NOIP模拟 水管(简单构造)

    传送门 仔细读题会发现只要所有点点权之和等于0一定有解. 如何构造? 直接当做树来构造就行了,非树边都赋值成0就行. 代码

  5. mount 移动硬盘出现的各种小问题

    1.fdisk -l 查看硬盘是否存在 2.新建要挂载硬盘的文件夹 mkdir  /disk   (如果想要挂载到已存在的目录就不要新建了) 3.挂载硬盘:mount /dev/sdc /disk 4 ...

  6. IntelliJ IDEA 2017版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA环境搭建,JPA实现非字符型设置长度

    1.在github上已有配置环境,如下链接,(需要环境JDK1.8及以上版本,Tomcat1.8及以上版本,搭建maven库,使用编译器IntellJ IDEA) https://github.com ...

  7. Effective C++ 随笔(5)

    条款27:尽量稍作转型动作 const_cast:常量性移除 dynamic_cast:安全向下转型 reinterpret_cast: static_cast: 如在子类当中享调用父类当中的某个方法 ...

  8. rpcbind.service启动失败

    新装的服务器,启动rpcbind.service通常失败,执行下面的两个命令经常卡死,一直不返回,也不报错 #systemctl start nfs-server.service #systemctl ...

  9. Java技术----Java泛型详解

    1.为什么需要泛型 泛型在Java中有很重要的地位,网上很多文章罗列各种理论,不便于理解,本篇将立足于代码介绍.总结了关于泛型的知识.希望能给你带来一些帮助. 先看下面的代码: List list = ...

  10. java poi 合并单元格

    java poi 合并单元格 2017年03月29日 16:39:01 翠烟你懊恼 阅读数:26561   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.n ...