今天程序考试受挫,遂打算寒假空闲时间刷刷题,练练手感。
今天有一题是这样的,文件"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;
}