算法刷题记录:
状态压缩动态规划刷题记录
问题描述
提示:这里描述题目中的问题:
n个人在玩传球游戏,传球之间随意,遍历所有状态,实现整个动态规划过程!
解题思路:压缩动态规划
问题:球传递 开始时球在在n个人中任一位手里, 每次传递 都不传给重复的人 且每次传递有代价,不同人之间传递的代价间没有联系。
求:当球经过所有n个人后,整个过程的最低总代价为多少。
//完整代码 带注释
//#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
using namespace std;
#include<queue>
#include <cstring>
const int INF = 0x3f;
int a[20][20];
//一维状态 经历了哪些人的手 二维状态保存 球的哪位手上
int dp[1 << 16][20];
int main() {
int n, m;
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];//a[i][j] 从i传到j的代价
}
}
// 第i位为1 i
//初始化状态 开始球可以在任何人手里dp[1 << i][i] = 0; 其他状态无穷大 代价
memset(dp, 0x3f, sizeof(dp));
for (int i = 0; i < n; i++) {
//dp表示 球经过了第i个人的手,现在在 第i个人的手上状态
dp[1 << i][i] = 0;
}
//枚举所有可行的状态
for (int i = 0; i < (1 << n); i++) {//哪些人手上经过了球 1维状态
//二维状态:这个球现在在哪个人手上
for (int j = 0; j < n; j++) {
//这个人在1维状态里 不存在矛盾
if (i & (1 << j)) {
//不冲突 枚举 从j传给k
for (int k = 0; k < n; k++) {
//k不能在i集合里面 就是 传给没传过的人手里
if (!(i & 1 << k)) {
//状态转移方程 在i的集合里 加上第k位 dp[i | 1 << k][k]
dp[i | 1 << k][k] = min(dp[i | 1 << k][k], dp[i][j] + a[j][k]);
}
}
}
}
}
//枚举最后球在谁手上 最优解 111111
int ans = INF;
for (int i = 0; i < n; i++) {
ans = min(ans, dp[(1 << n) - 1][i]);
}
cout << ans << endl;
return 0;
}
输入:
第一行 n个人 下面n行为传递球的代价
输入样例
3
-1 2 4
3 -1 5
4 4 -1
输出:一个最小代价值
6
![测试](https://img-blog.csdnimg.cn/c7ccbae1087140648ab190ef31869494.png#pic_center)
# 自述:
第一次写东西
记录代码 为自己以后复习用
@[671](c++自学之路)