c++状压dp——超实用的数据结构

目录

1. 二进制常用操作

1.1 在了解状压dp之前,我们需要复习一下二进制:

1.2 二进制模拟集合:

2. 状压dp

2.1 实现方法

2.2 代码


1. 二进制常用操作

1.1 在了解状压dp之前,我们需要复习一下二进制:

取出整数n在二迸制表示下的第k位: (n >>k) &1
把整数n在二逬制表示下的第 k位取反:n ^ (1<<k)
対整数n在二逬制表示下的第k位赋值1:n |(1 <<k)
対整数n在二逬制表示下的第k位赋值0:n & (~1 <<k))

1.2 二进制模拟集合:

2. 状压dp

2.1 实现方法

让我们先看一道例题:最短哈密尔顿路径 - LUKE LABS Online Judge

用二进制数标记某个点是否经过,0 未经过,1表示经过,最短路径dp[state][x]

dp[1 << n - 1][ n - 1]

对于 状态(S, j),可以枚举 当前之所以处在位置j,是上一步从哪里走过来。枚举上一步 所在的位置k。得到转移方程 :

dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + a[k][j]) 

状态初值是  dp[1][0] = 0

时间复杂度分析:状态数 * 状态转移时间复杂度

2.2 代码

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 20, M = 1 << N;
int n, a[N][N], dp[M][N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
     // 输入n个点 和 每个点之间的距离
    cin >> n;                        
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) {
            cin >> a[i][j];
        }

    // 使用dp[state][x]标记 经过二进制的state的某个点 最后停留x点上的最短距离
    memset(dp, 0x3f, sizeof dp);          // 0x3f 代表无穷大
    dp[1][0] = 0;                         // 初始化 state = 1 停留在0点的最段距离为0

    for (int i = 0; i < 1 << n; i++)      // 遍历各种组合
        for (int j = 0; j < n; j++)       // j,k组合是0~n-1
            if (i >> j & 1) 
                for (int k = 0; k < n; k++)   // state(i必须经过k点,才可以判断)
                    if (i >> k & 1) {         // 判断i在二进制下的第k位是否为1
                        // 某个state二进制记录下,找出停留在k点上再加上k到j的距离,得到state二进制下,停留在j上的最短路径
                        dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + a[k][j]);
                    }

    // 输出0~n-1的state下停留在n-1点的最段距离, 复杂度0(N^2 * 2^n)
    cout << dp[(1 << n) - 1][n - 1] << "\n";

    return 0;
}


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值