您的位置:首页 > 其它

蓝桥杯 漏掉的账目明细 DFS搜索 数据处理

2015-03-14 12:17 232 查看
某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?

如果有多种可能,则输出所有可能的情况。

我们规定:用户输入的第一行是:有错的总金额。

接下来是一个整数n,表示下面将要输入的明细账目的条数。

再接下来是n行整数,分别表示每笔账目的金额。

要求程序输出:所有可能漏掉的金额组合。每个情况1行。金额按照从小到大排列,中间用空格分开。

比如:

用户输入:

6

5

3

2

4

3

1

表明:有错的总金额是6;明细共有5笔。

此时,程序应该输出:

1 3 3

1 2 4

3 4

为了方便,不妨假设所有的金额都是整数;每笔金额不超过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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐