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;
}
相关推荐
xieliyu.36 分钟前
Java算法精讲:双指针(三)
java·开发语言·算法
CryptoPP2 小时前
快速对接东京证券交易所API数据:实战指南与代码示例
开发语言·人工智能·windows·python·信息可视化·区块链
ZC跨境爬虫2 小时前
跟着 MDN 学JavaScript day_7:数学运算与逻辑判断实战测试
开发语言·前端·javascript·学习·ecmascript
阳区欠3 小时前
【LangChain】LLM基础介绍
开发语言·python·langchain
Jinkxs3 小时前
Java 跨域14-Java 与区块链(Hyperledger)集成
java·开发语言·区块链
晨曦中的暮雨4 小时前
Golang速通(Javaer版)
java·开发语言·后端·golang
小小编程路4 小时前
Python 还有容器类型互转、进制转换、字符编码转换
开发语言·windows·python
Qt程序员4 小时前
Linux RCU 原理与应用
linux·c++·内核·linux内核·rcu
qeen874 小时前
【C++】类与对象之类的默认成员函数(二)
android·c语言·开发语言·c++·笔记·学习
CRMEB系统商城5 小时前
CRMEB多商户系统(Java)v2.3公测版发布
java·开发语言·人工智能·小程序·开源·php