状压DP,对应蓝桥云课坐标搜索 代码框架见下
cpp
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 16
#define type double
#define dptype DPType::MIN
typedef type(*dis_func)(int a, int b);
enum DPType{
MIN = 0, //最大值
MAX = 1, //最小值
NUM = 2, //方案数
};
//
//
type dp[1 << maxn][maxn];
type dis[maxn][maxn];
type HamiltonDP_Opt(type a, type b, type c){
if(dptype == DPType::MIN){
return min(a, b+c);
}else if(dptype == DPType::MAX){
return max(a, b+c);
}else if(dptype == DPType::NUM){
return a + b * c;
}
}
type HamiltonDP_ValueInit(){
if(dptype == DPType::MIN){
return 0;
}else if(dptype == DPType::MAX){
return 0;
}else if(dptype == DPType::NUM){
return 1;
}
}
type HamiltonDP_ValueInf(){
if(dptype == DPType::MIN){
return 1000000000;
}else if(dptype == DPType::MAX){
return -1000000000;
}else if(dptype == DPType::NUM){
return 0;
}
}
void HamiltonDP_Init(int n, dis_func df){
memset(dp, -1, sizeof(dp));
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
dis[i][j] = df(i, j);
}
}
}
// state:二进制的1101 代表0 2 3 这三个顶点已经被访问的情况
// n :代表总共有多少个顶点
// pre :代表这条路径上的最后一个顶点
type HamiltonDP_DFS(int state, int n, bool isCircle, int start, int pre){
if(state + 1 == (1 << n)){
type init = HamiltonDP_ValueInit();
type inf = HamiltonDP_ValueInf();
if(isCircle){
//最小值:min(inf, init + dis[pre][start]);
//最大值:max(inf, init + dis[pre][start]);
return HamiltonDP_Opt(inf, init, dis[pre][start]);
}
return init;
}
type& ans = dp[state][pre];
if(ans >= 0){
return ans;
}
ans = HamiltonDP_ValueInf();
for(int i=0; i<n; ++i){
if(state & (1 << i)){
continue;
}
type d = dis[pre][i];
type next = HamiltonDP_DFS(state | (1 << i), n, isCircle, start, i);
ans = HamiltonDP_Opt(ans, d, next);
}
return ans;
}
type HamiltonDP_Solve(dis_func df, int n, bool isCircle, int start = -1){
// 初始化
HamiltonDP_Init(n, df);
type ans = HamiltonDP_ValueInf();
type ini = HamiltonDP_ValueInit();
if(start == -1){
for(int i = 0; i < n; ++i){
type v = HamiltonDP_DFS((1 << i), n, isCircle, i, i);
ans = HamiltonDP_Opt(ans, v, ini);
}
}else{
type v = HamiltonDP_DFS((1 << start), n, isCircle, start, start);
ans = HamiltonDP_Opt(ans, v, ini);
}
return ans;
}
int n;
int x[maxn], y[maxn];
type d(int a, int b){
return sqrt((x[a] - x[b]) * (x[a] - x[b]) +
(y[a] - y[b]) * (y[a] - y[b]));
}
int main()
{
cin >> n;
n++;
x[0] = y[0] = 0;
for(int i=1; i<n; ++i){
cin >> x[i] >> y[i];
}
printf("%.2lf\n", HamiltonDP_Solve(d, n, false, 0));
// 请在此输入您的代码
return 0;
}
代码练习1 回路计数 对应蓝桥云课 代码见下
cpp
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 21
#define type long long
#define dptype DPType::NUM
typedef type(*dis_func)(int a, int b);
enum DPType{
MIN = 0, //最大值
MAX = 1, //最小值
NUM = 2, //方案数
};
//
//
type dp[1 << maxn][maxn];
type dis[maxn][maxn];
type HamiltonDP_Opt(type a, type b, type c){
if(dptype == DPType::MIN){
return min(a, b+c);
}else if(dptype == DPType::MAX){
return max(a, b+c);
}else if(dptype == DPType::NUM){
return a + b * c;
}
}
type HamiltonDP_ValueInit(){
if(dptype == DPType::MIN){
return 0;
}else if(dptype == DPType::MAX){
return 0;
}else if(dptype == DPType::NUM){
return 1;
}
}
type HamiltonDP_ValueInf(){
if(dptype == DPType::MIN){
return 1000000000;
}else if(dptype == DPType::MAX){
return -1000000000;
}else if(dptype == DPType::NUM){
return 0;
}
}
void HamiltonDP_Init(int n, dis_func df){
memset(dp, -1, sizeof(dp));
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
dis[i][j] = df(i, j);
}
}
}
// state:二进制的1101 代表0 2 3 这三个顶点已经被访问的情况
// n :代表总共有多少个顶点
// pre :代表这条路径上的最后一个顶点
type HamiltonDP_DFS(int state, int n, bool isCircle, int start, int pre){
if(state + 1 == (1 << n)){
type init = HamiltonDP_ValueInit();
type inf = HamiltonDP_ValueInf();
if(isCircle){
//最小值:min(inf, init + dis[pre][start]);
//最大值:max(inf, init + dis[pre][start]);
return HamiltonDP_Opt(inf, init, dis[pre][start]);
}
return init;
}
type& ans = dp[state][pre];
if(ans >= 0){
return ans;
}
ans = HamiltonDP_ValueInf();
for(int i=0; i<n; ++i){
if(state & (1 << i)){
continue;
}
type d = dis[pre][i];
type next = HamiltonDP_DFS(state | (1 << i), n, isCircle, start, i);
ans = HamiltonDP_Opt(ans, d, next);
}
return ans;
}
type HamiltonDP_Solve(dis_func df, int n, bool isCircle, int start = -1){
// 初始化
HamiltonDP_Init(n, df);
type ans = HamiltonDP_ValueInf();
type ini = HamiltonDP_ValueInit();
if(start == -1){
for(int i = 0; i < n; ++i){
type v = HamiltonDP_DFS((1 << i), n, isCircle, i, i);
ans = HamiltonDP_Opt(ans, v, ini);
}
}else{
type v = HamiltonDP_DFS((1 << start), n, isCircle, start, start);
ans = HamiltonDP_Opt(ans, v, ini);
}
return ans;
}
int n;
int x[maxn], y[maxn];
int gcd(int a, int b){
return !b ? a : gcd(b, a%b);
}
type d(int a, int b){
return gcd(a+1, b+1) == 1;
}
int main()
{
int n = 21;
printf("%.lld\n", HamiltonDP_Solve(d, n, true, 0));
// 请在此输入您的代码
return 0;
}
代码练习 2 星球 对应蓝桥云课 代码见下
cpp
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 18
#define type double
#define dptype DPType::MIN
typedef type(*dis_func)(int a, int b);
enum DPType{
MIN = 0, //最大值
MAX = 1, //最小值
NUM = 2, //方案数
};
//
//
type dp[1 << maxn][maxn];
type dis[maxn][maxn];
type HamiltonDP_Opt(type a, type b, type c){
if(dptype == DPType::MIN){
return min(a, b+c);
}else if(dptype == DPType::MAX){
return max(a, b+c);
}else if(dptype == DPType::NUM){
return a + b * c;
}
}
type HamiltonDP_ValueInit(){
if(dptype == DPType::MIN){
return 0;
}else if(dptype == DPType::MAX){
return 0;
}else if(dptype == DPType::NUM){
return 1;
}
}
type HamiltonDP_ValueInf(){
if(dptype == DPType::MIN){
return 1000000000;
}else if(dptype == DPType::MAX){
return -1000000000;
}else if(dptype == DPType::NUM){
return 0;
}
}
void HamiltonDP_Init(int n, dis_func df){
memset(dp, -1, sizeof(dp));
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
dis[i][j] = df(i, j);
}
}
}
// state:二进制的1101 代表0 2 3 这三个顶点已经被访问的情况
// n :代表总共有多少个顶点
// pre :代表这条路径上的最后一个顶点
type HamiltonDP_DFS(int state, int n, bool isCircle, int start, int pre){
if(state + 1 == (1 << n)){
type init = HamiltonDP_ValueInit();
type inf = HamiltonDP_ValueInf();
if(isCircle){
//最小值:min(inf, init + dis[pre][start]);
//最大值:max(inf, init + dis[pre][start]);
return HamiltonDP_Opt(inf, init, dis[pre][start]);
}
return init;
}
type& ans = dp[state][pre];
if(ans >= 0){
return ans;
}
ans = HamiltonDP_ValueInf();
for(int i=0; i<n; ++i){
if(state & (1 << i)){
continue;
}
type d = dis[pre][i];
type next = HamiltonDP_DFS(state | (1 << i), n, isCircle, start, i);
ans = HamiltonDP_Opt(ans, d, next);
}
return ans;
}
type HamiltonDP_Solve(dis_func df, int n, bool isCircle, int start = -1){
// 初始化
HamiltonDP_Init(n, df);
type ans = HamiltonDP_ValueInf();
type ini = HamiltonDP_ValueInit();
if(start == -1){
for(int i = 0; i < n; ++i){
type v = HamiltonDP_DFS((1 << i), n, isCircle, i, i);
ans = HamiltonDP_Opt(ans, v, ini);
}
}else{
type v = HamiltonDP_DFS((1 << start), n, isCircle, start, start);
ans = HamiltonDP_Opt(ans, v, ini);
}
return ans;
}
int n;
int x[maxn], y[maxn], z[maxn], w[maxn+1];
type d(int a, int b){
return sqrt((x[a] - x[b]) * (x[a] - x[b]) +
(y[a] - y[b]) * (y[a] - y[b])
+ (z[a] - z[b]) * (z[a] - z[b])) * w[b];
}
int main()
{
cin >> n;
for(int i=0; i<n; ++i){
cin >> x[i] >> y[i] >> z[i] >> w[i];
}
printf("%.2lf\n", HamiltonDP_Solve(d, n, false, -1));
// 请在此输入您的代码
return 0;
}
代码练习 3 对应蓝桥云课 补给 代码见下
cpp
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 20
#define type double
#define dptype DPType::MIN
typedef type(*dis_func)(int a, int b);
enum DPType{
MIN = 0, //最大值
MAX = 1, //最小值
NUM = 2, //方案数
};
//
//
type dp[1 << maxn][maxn];
type dis[maxn][maxn];
type HamiltonDP_Opt(type a, type b, type c){
if(dptype == DPType::MIN){
return min(a, b+c);
}else if(dptype == DPType::MAX){
return max(a, b+c);
}else if(dptype == DPType::NUM){
return a + b * c;
}
}
type HamiltonDP_ValueInit(){
if(dptype == DPType::MIN){
return 0;
}else if(dptype == DPType::MAX){
return 0;
}else if(dptype == DPType::NUM){
return 1;
}
}
type HamiltonDP_ValueInf(){
if(dptype == DPType::MIN){
return 1000000000;
}else if(dptype == DPType::MAX){
return -1000000000;
}else if(dptype == DPType::NUM){
return 0;
}
}
void HamiltonDP_Init(int n, dis_func df){
memset(dp, -1, sizeof(dp));
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
dis[i][j] = df(i, j);
}
}
}
// state:二进制的1101 代表0 2 3 这三个顶点已经被访问的情况
// n :代表总共有多少个顶点
// pre :代表这条路径上的最后一个顶点
type HamiltonDP_DFS(int state, int n, bool isCircle, int start, int pre){
if(state + 1 == (1 << n)){
type init = HamiltonDP_ValueInit();
type inf = HamiltonDP_ValueInf();
if(isCircle){
//最小值:min(inf, init + dis[pre][start]);
//最大值:max(inf, init + dis[pre][start]);
return HamiltonDP_Opt(inf, init, dis[pre][start]);
}
return init;
}
type& ans = dp[state][pre];
if(ans >= 0){
return ans;
}
ans = HamiltonDP_ValueInf();
for(int i=0; i<n; ++i){
if(state & (1 << i)){
continue;
}
type d = dis[pre][i];
type next = HamiltonDP_DFS(state | (1 << i), n, isCircle, start, i);
ans = HamiltonDP_Opt(ans, d, next);
}
return ans;
}
type HamiltonDP_Solve(dis_func df, int n, bool isCircle, int start = -1){
// 初始化
HamiltonDP_Init(n, df);
type ans = HamiltonDP_ValueInf();
type ini = HamiltonDP_ValueInit();
if(start == -1){
for(int i = 0; i < n; ++i){
type v = HamiltonDP_DFS((1 << i), n, isCircle, i, i);
ans = HamiltonDP_Opt(ans, v, ini);
}
}else{
type v = HamiltonDP_DFS((1 << start), n, isCircle, start, start);
ans = HamiltonDP_Opt(ans, v, ini);
}
return ans;
}
int n;
type d[maxn][maxn];
int x[maxn], y[maxn];
type df(int a, int b){
return d[a][b];
}
int main()
{
int n, D;
cin >> n >> D;
for(int i=0; i<n; ++i){
cin >> x[i] >> y[i];
}
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
int xx = x[i] - x[j];
int yy = y[i] - y[j];
int di = xx*xx + yy*yy;
if(di <= (long long)D * D){
d[i][j] = sqrt(di);
}else{
d[i][j] = HamiltonDP_ValueInf();
}
}
}
for(int k=0; k<n; ++k){
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
if(d[i][k] + d[k][j] < d[i][j]){
d[i][j] = d[i][k] + d[k][j];
}
}
}
}
printf("%.2lf\n", HamiltonDP_Solve(df, n, true, 0));
// 请在此输入您的代码
return 0;
}