您的位置:首页 > 其它

子集和问题

2015-11-12 17:53 302 查看
input.txt

5 10

2 4 6 5 2

#include <iostream>
#include <fstream>
using namespace std;

class subset{
public:subset(int* best, int* arr, int n, int result);
void backtrack();
bool Place(int k);
int* arr;//序列各个个数的值
int n;//数字总个数
int *x;//当前解
int *best;//最优解
int r;//剩下的序列和
int nresult;//当前序列的总和
int result;//目的序列和
};

subset::subset(int* best, int* arr, int n, int result){
this->best = best;
this->arr = arr;
this->n = n;
this->result = result;
x = new int[n + 1];
r = 0;
for (int i = 0; i < n; i++){
r += arr[i];
}
}

bool subset::Place(int k){//第k个不装的情况下当前序列和剩下的和是否能组成result
if ((nresult + r) < result)return false;
return true;
}

void subset::backtrack(){//向左孩子出生条件nresult+arr[k]<result,右孩子出生条件Place()
x[1] = 0;
int k = 1;
nresult = 0;
//搜索子树
while (true){
while ((k <= n) && (nresult + arr[k] <= result)){//从k节点开始一直向左
r -= arr[k];
nresult += arr[k];
x[k] = 1;
k++;
}
if (k > n){//到达终点
if (nresult == result){//找到节点结束
for (int j = 1; j <= n; j++){
best[j] = x[j];
}
return;
}
else{//返回到最后后一次进入队列的节点
k--;//退回到叶子节点
r += arr[k];//释放资源
nresult -= arr[k];//释放资源
k--;//找最后一次加入的节点
while (k > 0 && !x[k]){//从右子树返回
r += arr[k];
k--;
}
nresult -= arr[k];
x[k] = 0;
k++;
}
}
else{//进入右子树
r -= arr[k];
x[k] = 0;
k++;
}
}
}

int main(){
//数据读取
ifstream in("input.txt", ios::in);
if (!in.is_open()){
cout << "Error opening file";
exit(1);
}
char ch;
int n = in.get() - '0';//子集个数
while ((ch = in.get()) != ' '){
n = n * 10 + ch - '0';
}
int* arr = new int[n+1];
int result = in.get() - '0';//记录序列和
while ((ch = in.get()) != '\n'){
result = result * 10 + ch - '0';
}

int i = 1;
while (!in.eof()){
arr[i] = in.get() - '0';
while( ((ch = in.get()) != ' ')&&(ch!= '\n')&&(ch!=-1)){
arr[i] = arr[i] * 10 + ch - '0';
}
i++;
}
/*
for (int i = 0; i < n; i++){
cout << arr[i] << " " << endl;
}
*/
in.close();
//数据处理
int* best = new int[n+1]();//标记最优解
subset demo(best,arr,n,result);
demo.backtrack();
for (int i = 1; i <= n; i++){
if (best[i] == 1)cout << arr[i] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: