C++状压DP

状压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;
}
相关推荐
炸膛坦客43 分钟前
单片机/C/C++八股:(二十)指针常量和常量指针
c语言·开发语言·c++
兑生1 小时前
【灵神题单·贪心】1481. 不同整数的最少数目 | 频率排序贪心 | Java
java·开发语言
炸膛坦客2 小时前
单片机/C/C++八股:(十九)栈和堆的区别?
c语言·开发语言·c++
零雲2 小时前
java面试:了解抽象类与接口么?讲一讲它们的区别
java·开发语言·面试
Jay_Franklin2 小时前
Quarto与Python集成使用
开发语言·python·markdown
2401_831824963 小时前
代码性能剖析工具
开发语言·c++·算法
是wzoi的一名用户啊~3 小时前
【C++小游戏】2048
开发语言·c++
Sunshine for you4 小时前
C++中的职责链模式实战
开发语言·c++·算法
@我漫长的孤独流浪4 小时前
Python编程核心知识点速览
开发语言·数据库·python
qq_416018724 小时前
C++中的状态模式
开发语言·c++·算法