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



某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某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;
}


你可能感兴趣的:(ACM,数据处理,蓝桥杯,dfs搜索,漏掉的账目明细)