蓝桥杯 漏掉的账目明细 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;
}
如果有多种可能,则输出所有可能的情况。
我们规定:用户输入的第一行是:有错的总金额。
接下来是一个整数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;
}
相关文章推荐
- 备考蓝桥杯(26)漏掉的账单明细,(遍历所有情况)(java实现)(exforward)
- 金额查错:某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔, 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
- 蓝桥杯 方块填数 DFS搜索
- 蓝桥杯 算法训练 单词接龙 _DFS_搜索 字符串比较
- (算法)DFS深度优先搜索—2016年蓝桥杯省赛java剪邮票
- 金额查错:某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔, 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
- 蓝桥杯——漏掉的账目
- 蓝桥杯 历届试题 剪格子(dfs搜索)
- 2013年第四届蓝桥杯C/C++省赛 第39级台阶(结果填空) ----DFS深度搜索遍历和暴力搜索
- 漏掉的账目明细
- 蓝桥杯 算法提高 3000米排名预测 DFS 递归搜索 next_permutation()使用
- 某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
- 蓝桥杯 历届试题 剪格子(dfs搜索)
- 蓝桥杯 排列数(DFS搜索)
- 2016年蓝桥杯省赛A组C/C++ 第二题 跳蚱蜢(dfs搜索+状态压缩)
- 蓝桥杯历届试题 大臣的旅费 记忆化搜索DFS
- 深度优先搜索DFS
- 2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS
- 搜索(DFS)
- 蓝桥杯—李白打酒 dfs