CS_C/C++_BackTracking

概念

  • 扩展节点:一个正在产生儿子的结点
  • 活节点:一个自身已生产但其儿子还没有全部生成的结点
  • 死结点:一个所有儿子已经产生的结点

回溯法解决0/1背包问题

BackTracking_zzk.cpp
//
//  BackTracking_zzk.cpp
//  algorithm
//
//  Created by 支泽楷 on 2020/5/2.
//  Copyright © 2020 支泽楷. All rights reserved.
//

#include "BackTracking_zzk.hpp"
#include <iostream>
using namespace std;
int n; //物品数量
double c; //背包容量
double* value; //物品价格数组
double* weight; //物品重量数组
int *order;
double cw = 0.0; //   当前背包重量
double cp = 0.0;  //当前背包总价值
int  *best_item_list;
int  *item_list;
int best_value = 0; //最优价值

//上界函数,return 当前分支的最大价值
double bound(int i) {
    double capacity_left = c - cw; //剩余背包容量
    double total_value = cp;        //背包全部价值
    
    while (i <= n && weight[i] <= capacity_left) {
        capacity_left -= weight[i];
        total_value += value[i];
        i++;
    }
    
    if (i <= n) {
        total_value += value[i]/weight[i] * capacity_left;
    }
    
    return total_value;
}

//按单位价值排序
double knapsack(double *pp,   //价值(1,n)
              double *ww,   //重量(1,n)
              double cc    //背包容量
            ) { 
    int i = 0,j;
    
    //以单位价值排序的数组
    UnitValue *unitValueList  = new UnitValue[n+1];//(1,n)
    double ws = 0.0;
    double ps = 0.0;
    
    //创建单位价值数组,重量价值求和
    for (int i = 1; i <= n; i++) {
        unitValueList[i] = UnitValue(i,pp[i]/ww[i]);
        ps = ps + pp[i];
        ws = ws + ww[i];
    }
    
    if(ws <= c) {return ps;}
    
    //冒泡排序
    double temp = 0.0;
    for (i = 1; i <= n ; i ++) {
        for (j = 1; j<= n - i;j++ ){
            //descent order
            if (unitValueList[j].unit_value < unitValueList[j+1].unit_value) {
                
                //单位价值排序
                UnitValue unitValueTemp = unitValueList[j];
                unitValueList[j+1] = unitValueList[j];
                unitValueList[j] = unitValueTemp;

                //物品id排序
                temp = order[j];
                order[j+1] = order[j];
                order[j] = temp;
                
                //价值排序
                temp = value[j+1];
                value[j+1] = value[j];
                value[j] = temp;
                
                //重量排序
                temp = weight[j+1];
                weight[j+1] = weight[j];
                weight[j] = temp;
            }
        }
    }
    
    return 0;
}

void backtrack(int i) {
//    double bound(i);
    
    //递归结束判定条件
    if (i > n) {
        
        best_value = cp;
        for (int _i=1; _i < i; _i++) {
            best_item_list[_i] = item_list[_i];
        }
        return;
    }
    
    if (cw + weight[i] <= c) {
        
        cw += weight[i];
        cp += value[i];
        item_list[i] = 1;
        
        backtrack(i+1);
        
        //回溯复原
        cw -= weight[i];
        cp -= value[i];
        item_list[i] = 0;
    }
    
    if(bound(i+1) > best_value) {
        backtrack(i+1);
    }
    
}

int backtrack_main() {
    int i;
//    cout << "请输入物品的数量和背包的容量:" << endl;
//    scanf("%d %lf",&n,&c);
    n = 3;c = 30;
    value = new double[n+1];// (1,n)
    weight = new double[n+1];
    order = new int[n+1];
    best_item_list = new int[n+1];
    item_list = new int[n+1];
//    printf("请依次输入%d个物品的重量:\n",n);
//    for(i=1;i<=n;i++){
//        cin >> weight[i];
//    }
//
//    printf("请依次输入%d个物品的价值:\n",n);
//    for(i=1;i<=n;i++){
//        cin >> value[i];
//
//    }
    
   
    weight[1] = 15;weight[2] = 16;weight[3] = 15;
    order[1] = 1;order[2]= 2;order[3] = 3;
    value[1] = 25;value[2] = 45;value[3] = 25;
    
    knapsack(value, weight, c);
    backtrack(1);
    
    cout << "最优价值为:" << best_value;
    cout << "\n需要装入的物品编号是:";
    for(i=1;i<=n;i++)
    {
        if(best_item_list[i]==1) {
            cout << order[i]<< " ";
        }
    }
    return 0;
}

BackTracking_zzk.hpp
//
//  BackTracking_zzk.hpp
//  algorithm
//
//  Created by 支泽楷 on 2020/5/2.
//  Copyright © 2020 支泽楷. All rights reserved.
//

#ifndef BackTracking_zzk_hpp
#define BackTracking_zzk_hpp

#include <stdio.h>
#include <iostream>
using namespace std;

class UnitValue {
public:
    int id; //物品索引
    double unit_value;  //物品的单位价值
    
    UnitValue() {
        
    }
    UnitValue(int _id,double _unit_value) {
        id = _id;
        unit_value = _unit_value;
    }
    
    int compareTo(UnitValue x) {
        double x_unit_value  = x.unit_value;
        if (unit_value < x_unit_value ) {
            return -1;
        }
        if (unit_value == x_unit_value) {
            return 0;
        }
        
        return 0;
    }
    
    bool equals (UnitValue x) {
        return unit_value == x.unit_value;
    }
};
//上界函数,return 当前分支的最大价值
double bound(int i);
double knapsack(double *pp,double *ww,double cc);
void backtrack(int i);

int backtrack_main();
#endif /* BackTracking_zzk_hpp */

N-Queens problem

NQueens.cpp
//
//  part5backtrace.cpp
//  algorithm
//
//  Created by 支泽楷 on 2020/5/10.
//  Copyright © 2020 支泽楷. All rights reserved.
//

#include "part5backtrace.hpp"
Queen::Queen() {
    sum = 0; n = 0; x = NULL;
}

Queen::~Queen() {
    delete x;
}

void Queen::setn(int num)
{
    n=num;
    x=new int[num+1];
}

bool Queen::Place(int t) {
    int i;
    
    for (i = 1; i < t; i++) { //检查当前t个皇后有没有冲突的
        if ((abs(t - i) == abs(x[i] - x[t])) || (x[i] == x[t])) { //不在对角线也不在同一列
            return false;
        }
    }
    return true;
}

void Queen::Backtrack(int t) { //第t个皇后,也是row
    int i;
    if (t > n) {
        sum++;
        outputX();
    }else {
        for (i = 1; i <= n; i++) { //如果这一层都搜索一遍之后还是没有可行的,就会退到上一个皇后的位置。
            x[t] = i;  //第t个皇后在第 i column
            if (Place(t)) {
                Backtrack(t + 1);
            }
        }
    }
}

void Queen::outputX()
{   int i;
    for (i=1; i<=n; i++) {
        cout<<x[i]<<" ";
    }
    cout<<endl;
}

void Queen::outputsum()
{
   cout<<"Total="<<sum<<endl;
}

int queen_main()
{
    Queen MyQueen;
    int number;
    cout<<"input the number of queens: ";
    cin>>number;
    MyQueen.setn(number);
    MyQueen.Backtrack(1);
    MyQueen.outputX();
    MyQueen.outputsum();
    return 0;
}

NQueens.hpp
//
//  part5backtrace.hpp
//  algorithm
//
//  Created by 支泽楷 on 2020/5/10.
//  Copyright © 2020 支泽楷. All rights reserved.
//

#ifndef part5backtrace_hpp
#define part5backtrace_hpp

#include <stdio.h>
#include <iostream>
#include <cmath>
using namespace std;

class Queen{
private:
    int n;  //皇后的数量
    int *x;
    int sum;
    
public:
    Queen();
    ~Queen();
    
    void setn(int num);
    bool Place(int t);
    void Backtrack(int t);
    void outputX();
    void outputsum();
};

int queen_main();

#endif /* part5backtrace_hpp */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值