0x01
1.最短Hamilton路径(二进制状压dp)
描述
给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径。 Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。
输入格式
第一行一个整数n。
接下来n行每行n个整数,其中第i行第j个整数表示点i到j的距离(一个不超过10^7的正整数,记为a[i,j])。
对于任意的x,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]>=a[x,z]。
输出格式
一个整数,表示最短Hamilton路径的长度。
我们定义f[i][j]表示“点被经过的状态“对应的二进制数为i(最低位为1表示编号为0的点被经过),当前处于点j时的最短路径,由此我们可知最终的答案为f[(1<<n)-1][n-1];
可知状态转移方程为f[i][j] = min(f[i][j],f[i^1<<j][k]+weight[k][j]);
其中i必须满足i>>j&1以及k必须满足i^1<<j>>k&1
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int weight[20][20];
int f[1 << 20][20];
int main() {
int n;
scanf("%d", &n);
int x;
for(int i=0;i<n;i++)
for (int j = 0; j < n; j++) {
scanf("%d", &x);
weight[i][j] = x;
}
memset(f, 0x3f, sizeof(f));
f[1][0] = 0;
for (int i = 0; i <= 1 << n; i++)
for (int j = 0; j < n; j++)if (i >> j & 1)
for (int k = 0; k < n; k++)if (i ^ 1 << j >> k & 1)
f[i][j] = min(f[i][j], f[i ^ 1 << j][k] + weight[k][j]);
printf("%d\n", f[(1 << n) - 1][n - 1]);
return 0;
}
2.成对变换
对于任意非负整数:
当n为偶数时,n xor 1 = n + 1;
当n为奇数时,n xor 1 =n - 1;
3.lowbit运算:
lowbit(n)定义为非负整数n在二进制表示下,“最低位的1以及其后面所有的0”构成的数值;
lowbit(n) = n & (-n)
证明过程如下:
对于任意非负整数n,将其取反,则n最低位1及其后面的0全部与~n相反,将其加1之后,前文所提部分变成了...1000000的样子,将(~n+1)&n即lowbit(n),又因为在补码状态下,~n=-n-1;
证毕
对于1<<35以内的数字,可以用以下方法来以O(1)的时间复杂度来输出其所有1的位置
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int H[37];
int main() {
for (int i = 0; i <= 35; i++)H[(1LL << i) % 37] = i;
int n;
while (cin >> n) {
while (n > 0) {
printf("%d\n", H[(n & -n) % 37]);
n -= (n & -n);
}
}
return 0;
}
0x02
1.递归实现指数型枚举
从1~n随机选取任意多个,输出所有可能
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
using namespace std;
int n; vector<int>v;
void solve(int x) {
if (v.size() == n || x > n) {
for (auto i : v)
printf("%d ", i);
printf("\n");
return;
}
v.push_back(x);
solve(x + 1);
v.pop_back();
solve(x + 1);
}
int main() {
scanf("%d", &n);
solve(1);
return 0;
}
这篇博客探讨了如何解决图论问题中最短Hamilton路径的二进制动态规划算法,以及利用位操作进行高效计算的技巧。同时介绍了递归实现指数型枚举的方法,用于在一定范围内生成所有可能的子集。文章涵盖了图的最短路径计算、位操作应用和递归枚举策略,展示了计算机科学中算法和数据结构的应用。
1069

被折叠的 条评论
为什么被折叠?



