今天程序考试受挫,遂打算寒假空闲时间刷刷题,练练手感。
今天有一题是这样的,文件"data.txt"有N+1行,每一行都为一个正整数,第一行为N,剩余N行为任意N个正整数。对于正整数m(m>=2),输出m个数的和,要求和不大于100,并列出表达式;并且要求表达式不相同。若表达式中的元素相同则表达式就相同,如“1+2+3”与"2+1+3"相同,"2+2+4+4"与"4+2+2+4"相同。考虑所有可能的m,并且输出对应m所有的表达式到文件"output.txt"中。
题目的实质是子集和问题,给定元素个数为n的集合S,输出所有子集和小于100的子集。我们已知子集和问题是一个NP完全性问题(参考算法导论NP问题),所以该题目前不存在一个多项式时间的算法求解。
求解此问题可以采取递归算法,递归函数如下:
void output(vector<int> in, vector<int> out,int index) { vector<int> res; int sum=0; for(int i=0;i<out.size();i++) { sum += out[i]; res.push_back(out[i]); } sum+=in[index]; if(sum<=100) { res.push_back(in[index]); print(res); for(int j=index+1;j<in.size();j++) { output(in,res,j); } } }
然后在主函数中调用:
for(int i=0;i<n;i++) { output(vec,res,i); }另外需要完成表达式去重,这里采用的是最暴力的方法,完整代码如下(vs2012编译运行通过):
// testdemo.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <vector> #include <algorithm> #include <iostream> #include <string> #include <fstream> using namespace std; struct node { vector<int> vec; bool flag; }; ofstream out("output.txt"); vector<node> temp; void print(vector<int> v) { if(v.size()>1) { for(int i=0;i<v.size();i++) { out<<v[i]; if(i!=v.size()-1) out<<'+'; } out<<endl; } } void print_c(vector<int> v) { if(v.size()>1) { for(int i=0;i<v.size();i++) { cout<<v[i]; if(i!=v.size()-1) cout<<'+'; } cout<<endl; } } bool comp(vector<int> a, vector<int> b) { sort(a.begin(),a.end()); sort(b.begin(),b.end()); if(a.size()!=b.size()) return false; for(int i=0;i<a.size();i++) { if(a[i]!=b[i]) return false; } return true; } void output(vector<int> in, vector<int> out,int index) { vector<int> res; int sum=0; for(int i=0;i<out.size();i++) { sum += out[i]; res.push_back(out[i]); } sum+=in[index]; if(sum<=100) { res.push_back(in[index]); //print(res); struct node a ={res,false}; temp.push_back(a); for(int j=index+1;j<in.size();j++) { output(in,res,j); } } } int _tmain(int argc, _TCHAR* argv[]) { ifstream in("data.txt"); string str; vector<int> vec,res; in>>str; int n = atoi(str.c_str()); while(in>>str) { vec.push_back(atoi(str.c_str())); } sort(vec.begin(),vec.end()); for(int i=0;i<n;i++) { output(vec,res,i); } vector<vector<int>> vecArray; for(int i=0;i<temp.size();i++) { if(temp[i].flag==false) { for(int j=i+1;j<temp.size();j++) { if(comp(temp[i].vec,temp[j].vec)) { temp[j].flag=true; } } vecArray.push_back(temp[i].vec); } } for(int i=0;i<vecArray.size();i++) { print(vecArray[i]); } return 0; }