一、01背包问题
通过回溯算法,依次考虑每一个物品是否放入的情况
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
/*
数据格式
(物品重量)2,5,9,10
(物品价值)4,5,6,8
*/
class Solution{
private:
vector<int>::iterator dataItr;//指向数据首地址的迭代器
bool* resultPtr;//指向结果的指针
bool* tempResult;//临时结果指针
int size;//记录背包最大重量
int num;//记录物件数目
int value;//记录最大价值
public:
Solution(vector<int>::iterator dataItr,int size,int num) {
this->dataItr = dataItr;
this->size = size;
this->num = num;
this->value = 0;
this->tempResult = new bool[num];
this->resultPtr = new bool[num];
memset(this->tempResult, false, sizeof(bool) * num);
memset(this->resultPtr, false, sizeof(bool) * num);
}
void backtrack(int pos,int tempValue) {
if (pos == this->num) {//如果到头了则比较结果
if (this->value < tempValue) {
this->value = tempValue;
for (int i = 0;i < this->num;i++) {
this->resultPtr[i] = this->tempResult[i];
}
}
return;
}
//计算负重
this->size = this->size - this->dataItr[pos];
if (this->size < 0) {//如果超过了,则没有选择只能不放入
this->size = this->size + this->dataItr[pos];//复原
backtrack(pos + 1, tempValue);
return;
}
else {
//放入
tempResult[pos] = true;
tempValue = tempValue + dataItr[pos + this->num];//添加
backtrack(pos + 1, tempValue);
tempResult[pos] = false;
//不放入
this->size = this->size + this->dataItr[pos];//复原
tempValue = tempValue - dataItr[pos + this->num];//复原
backtrack(pos + 1, tempValue);
return;
}
}
void output() {
cout << "最大价值为:" << this->value <<endl<<"安排为:"<< endl;
for (int i = 0;i < num;i++) {
if (this->resultPtr[i]) {
cout << i << " ";
}
}
}
};
int main() {
int num = 0;//记录物件数目
int size = 0;//记录背包最大重量
vector<int> data;//记录数据
ifstream ifs("data.txt", ios_base::binary);
while (!ifs.eof()) {//记录有多少种
int count;
ifs >> count;//读取数据
if (ifs.fail()) {//出问题则跳过
ifs.clear();
ifs.ignore(1);
continue;
}
num++;
data.push_back(count);
}
ifs.close();
ifs.clear();
num = num / 2;
cout << "请输入背包能承受的最大重量" << endl;
cin >> size;
Solution solve(data.begin(), size, num);
solve.backtrack(0,0);
solve.output();
return 0;
}
改进:如果在进行回溯之前先进行依照重量从小到大排序,将是否下递归用一个if句作为判断。当体积超过时,可通过返回false,省略多余的递归调用。
二、运动员最佳配对问题
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
private:
int value;//记录最大值
int count;//记录男女人数
vector<vector<int>>::iterator pIter;//指向P头部
vector<vector<int>>::iterator qIter;//指向Q头部
vector<bool> Q;//记录Q中安排情况
public:
Solution(vector<vector<int>>::iterator pIter, vector<vector<int>>::iterator qIter,int count) {
this->value = 0;
this->pIter = pIter;
this->qIter = qIter;
this->count = count;
this->Q = vector<bool>(count, false);
}
bool backtrack(int pre,int tempValue) {
if (pre == this->count) {
this->value = (this->value < tempValue) ? tempValue : this->value;
return true;
}
int pos = 0;
while (pos < count) {//如果Q找完了,则结束
if (!Q[pos]) {//如果Q未被安排
Q[pos] = true;//安排
tempValue += pIter[pre][pos] * qIter[pos][pre];
if (backtrack(pre + 1, tempValue)) {//为true代表一个分支找完,不需要继续
Q[pos] = false;//移除
tempValue -= pIter[pre][pos] * qIter[pos][pre];
return false;
}
Q[pos] = false;//移除
tempValue -= pIter[pre][pos] * qIter[pos][pre];
}
pos++;
}
return false;
}
int result() { return this->value; }
};
int main() {
int num = 0;//记录男女人数
vector<vector<int>>P;//记录数据P
vector<vector<int>> Q;//记录数据Q
int count = 0;
ifstream ifs("input.txt", ios_base::binary);
ofstream ofs("output.txt", ios::binary);
ifs >> num;
P = vector<vector<int>>(num, vector<int>(num,0));
Q = vector<vector<int>>(num, vector<int>(num, 0));
for (int i = 0;i < 2*num;i++) {
for (int j = 0;j < num;j++) {
if (i < num) {
ifs >> P[i][j];
}
else {
ifs >> Q[i-num][j];
}
if (ifs.fail()) {//出问题则跳过
ifs.clear();
ifs.ignore(1);
j--;
continue;
}
}
}
ifs.close();
ifs.clear();
Solution solve(P.begin(),Q.begin(),num);
solve.backtrack(0,0);
ofs << solve.result();
return 0;
}