为了方便,不妨假设所有的金额都是整数;每笔金额不超过1000,金额的明细条数不超过100。
这道题目与立方和等式那道题有点类似,都是在一组数中不重复的取数,只不过那道题是排列,而这道题是组合,也就是从题目中给出的一组数据num[]中找出几个数,他们的和为w_sum,也就是那个错误的总金额,而除了这几个数的其他数字就是我们要找的,用DFS搜索,给每个数字分配一个标记,表示是否已使用,如果递归到某一步的和超过w_sum了,那么直接结束,如果相等的话,说明找到了一组数据,我们需要先在结果数组result[]中搜索一下这组解是否已经存在,如果不存在,就存到数组中,最后,输出结果数组。
#include<iostream> #include<stdio.h> #include<memory.h> #include<algorithm> using namespace std; int num[100],result[100][100],temp[100]; bool used[100]; int p,s; void init() { p=0,s=0; memset(used,false,sizeof(used)); for(int i=0;i<100;i++) { num[i]=10000; for(int j=0;j<100;j++) result[i][j]=10000; } } void showResult() { int i,j; for(i=0;i<p;i++) { for(j=0;result[i][j]!=10000;j++) cout<<result[i][j]<<' '; cout<<endl; } } bool cmp(int len) { int i,j; for(i=0;i<p;i++) { for(j=0;j<len;j++) { if(result[i][j]!=temp[j]) break; } if(j==len) return false;//正常退出说明存在一模一样的 } return true; } void save(int n) { int i,j,len; s=0; for(i=0;i<n;i++) { if(used[i]==false) { temp[s]=num[i]; s++; } } len=s; s=0; if(cmp(len)) { for(i=0;i<len;i++) result[p][i]=temp[i]; p++; } } void search(int sum,int n,int w_sum) { if(sum>w_sum) return; if(sum==w_sum) { save(n); return; } for(int i=0;i<n;i++) { if(used[i]==false) { used[i]=true; search(sum+num[i],n,w_sum); used[i]=false; } } } int main() { init(); int w_sum,n,i; cin>>w_sum>>n; for(i=0;i<n;i++) { cin>>num[i]; } sort(num,num+100); search(0,n,w_sum); showResult(); return 0; }