状压dp原理

简介: 笔记

状压DP


蒙德里安的梦想

求把N∗M的棋盘分割成若干个1*2的的长方形,有多少种方案。


先考虑横着放的情况 竖着放的自然唯一确定


状态表示

f[i][j]表示第i 列的每一行小方格被占用的情况j为二进制数 1表示占用


状态计算

用j 表示i列的状态k表示i−1列的状态


能从i−1列转移到i列的条件


① 两列没有冲突的情况 j & k = = 0


②第i−1列所有连续的空白格为偶数j∣k不存在连续奇数个0

const int N = 12, M = 1 << N;
LL f[N][M];
bool st[M];
int n, m;
int main() {
  while (cin >> n >> m, n || m) {
    memset(f, 0, sizeof f);
    for (int i = 0;i < 1 << n;++i) {//枚举1到n的每一个二进制数
      st[i] = true;//假设成立
      int cnt = 0;//当前这一段连续0的个数
      for (int j = 0; j < n;++j) {
        if ((i >> j) & 1) {//如果第j位为1 说明上一段连续的0已经结束
          if (cnt & 1)st[i] = false; // 如果为奇数 不成立
          cnt = 0; // 重置cnt
        }
        else cnt++;
      }
      if (cnt & 1)st[i] = false; //判断最后一段是否合法
    }
    f[0][0] = 1;
    for (int i = 1;i <= m;++i) {//枚举每一列
      for (int j = 0;j < 1 << n;++j) {//枚举当前列的所有情况
        for (int k = 0;k < 1 << n;++k) {//枚举前一列的所有情况
          if ((j & k) == 0 && st[j | k])//如果没有冲突并且所有连续的空格为偶数
            f[i][j] += f[i - 1][k]; //更新状态
        }
      }
    }
    cout << f[m][0] << endl;;//所有第m列没有方格出来的方案数即为答案
  }
  return 0;
}


最短Hamilton路径


给定一张 n 个点的带权无向图,点从0 n−1 标号,求起点 0 到终点n−1 的最短Hamilton路径。 Hamilton路径的定义是从 0  到 n−1 不重不漏地经过每个点恰好一次。


状态表示

5.png

const int N = 21, M = 1 << N;
int f[M][N];
int mp[N][N];
int main() {
  int n;cin >> n;
  for (int i = 0; i < n;++i) { //读入图
    for (int j = 0; j < n;++j) {
      cin >> mp[i][j];
    }
  }
  memset(f, 0x3f, sizeof f);
  f[1][0] = 0; // 只经过一个点时 距离为0
  for (int i = 0;i < 1 << n;++i) { //状态为i
    for (int j = 0; j < n;++j) { // 以j为终点
      if (i >> j & 1)//经过了j这一点的状态才有意义
        for (int k = 0; k < n;++k) //枚举从哪一个点转移过来
          if (i - (1 << j) >> k & 1) //没有经过j并且终点为k
            f[i][j] = min(f[i][j], f[i - (1 << j)][k] + mp[k]     [j]);
    }
  }
  cout << f[(1 << n) - 1][n - 1] << endl; //每一个点都经过 且终点为n-1
  return 0;
}


目录
相关文章
|
并行计算 Linux 测试技术
GPU实例使用--单实例上运行Linux桌面多开解决方案
客户前期使用的旧异构实例面临更新换代,新的推荐异构实例性能更强,客户的业务软件运行时,GPU使用率不高,需要探索多开方案,提高GPU使用率,提高实例性价比。
手机号码段自动生成器
海豚号码生成器,是一个在电脑上常用的办公软件。但是有些对电脑不太会操作的朋友们还是不太明白它的操作方法。它具有多种手机号码生成功能、号码导入手机通讯录和对号码进行综合整理的功能。具体说有这七种功能:手机号码随机生成功能、手机豹子号靓号生成功能、自定义手机号段生成功能、手机号码批量导入手机通讯录功能、杂乱文本中提取手机号码功能、手机号码打印前排版功能、手机号码综合整理功能。 下面我详细讲解七大功能之一的自定义手机号段生成的操作方法,以便帮到更多不太会操作电脑软件的朋友们。 自导入号段生成的操作步骤: 第一步:导入号码段。你自己来输入某个前七位的号段,多个号段也可以批量导入,txt格式里面一个号段
手机号码段自动生成器
|
5月前
|
JSON 前端开发 Java
开箱即用的GO后台管理系统 Kratos Admin - 交互式API文档 Swagger UI
Kratos Admin 集成 Swagger UI,实现交互式 API 文档。通过 Buf 生成 OpenAPI 规范,并内嵌至服务,自动同步接口变动,提升调试与协作效率。
286 1
开箱即用的GO后台管理系统 Kratos Admin - 交互式API文档 Swagger UI
|
3月前
|
消息中间件 设计模式 人工智能
掌握全维度智能体提示词框架(CAP)重塑AI提示词工程​
本文介绍了全维度智能体提示词框架CAP,通过四层架构实现对AI智能体行为的精准控制,涵盖身份定义、能力调度、安全约束与执行优化,助力企业构建可控、可维护的AI应用系统。
654 0
|
关系型数据库 MySQL
cmd中输入net start mysql 提示:服务名无效或者MySQL正在启动 MySQL无法启动
cmd中输入net start mysql 提示:服务名无效或者MySQL正在启动 MySQL无法启动
|
11月前
|
人工智能 自然语言处理 安全
魔搭社区每周速递(12.08-12.14)
魔搭ModelScope本期社区进展:新增1599个模型,46个数据集,67个创新应用,8篇内容
364 7
魔搭社区每周速递(12.08-12.14)
|
机器学习/深度学习 人工智能 Ubuntu
|
NoSQL Ubuntu Java
在Ubuntu下安装Redis
【1月更文挑战第6天】在Ubuntu下安装Redis
807 110
|
负载均衡 网络协议 NoSQL
Envoy架构概览(10):热启动,动态配置,初始化,排水,脚本
Envoy架构概览(10):热启动,动态配置,初始化,排水,脚本
|
存储 缓存 前端开发
关于JWT Token 自动续期的解决方案
关于JWT Token 自动续期的解决方案
1928 1