ACM-DFS之SumItUp——hdu1258

来源:互联网 发布:网络课和直播课的区别 编辑:程序博客网 时间:2024/06/05 09:09

Sum It Up

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1258

Problem Description
Given a specified total t and a list of n integers, find all distinct sums using numbers from the list that add up to t. For example, if t=4, n=6, and the list is [4,3,2,2,1,1], then there are four different sums that equal 4: 4,3+1,2+2, and 2+1+1.(A number can be used within a sum as many times as it appears in the list, and a single number counts as a sum.) Your job is to solve this problem in general.

Input
The input will contain one or more test cases, one per line. Each test case contains t, the total, followed by n, the number of integers in the list, followed by n integers x1,...,xn. If n=0 it signals the end of the input; otherwise, t will be a positive integer less than 1000, n will be an integer between 1 and 12(inclusive), and x1,...,xn will be positive integers less than 100. All numbers will be separated by exactly one space. The numbers in each list appear in nonincreasing order, and there may be repetitions.

Output
For each test case, first output a line containing 'Sums of', the total, and a colon. Then output each sum, one per line; if there are no sums, output the line 'NONE'. The numbers within each sum must appear in nonincreasing order. A number may be repeated in the sum as many times as it was repeated in the original list. The sums themselves must be sorted in decreasing order based on the numbers appearing in the sum. In other words, the sums must be sorted by their first number; sums with the same first number must be sorted by their second number; sums with the same first two numbers must be sorted by their third number; and so on. Within each test case, all sums must be distince; the same sum connot appear twice.

Sample Input
4 6 4 3 2 2 1 1
5 3 2 1 1
400 12 50 50 50 50 50 50 25 25 25 25 25 25
0 0

Sample Output
Sums of 4:
4
3+1
2+2
2+1+1
Sums of 5:
NONE
Sums of 400:
50+50+50+50+50+50+25+25+25+25

50+50+50+50+50+25+25+25+25+25+25


DFS,刚开始做就一直在纠结,怎么来解决重复输出的问题呢?

我刚开始想的是建立一个结构体,记录每一个成功输出的时候,各个元素的个数。

后面成功的与前面成功的比较,但是,这个感觉做起来比较麻烦,应该有更简单的方法。

想+找+画→终于明白,

只需要在 单个递归函数中判断一个数不能出现两次即可:

以下面这组数据为例:


5 5 2 2 2 1 1

模拟一下:函数先后顺序用A B C D来表示,其实都是同一个函数,只是顺序不同。

函数A   选第一个2 ,标记在函数A中选了2

函数B   选第二个2,标记函数B中选了2

函数C   选第三个2,标记函数C中选了2

函数D   总和大于5  返回

函数C   向下选,选1,标记函数C中选了1(原来的2标记被覆盖)

函数E   符合条件,输出,返回

函数C   向下选,剩下1,因为1之前选过,不能再次选择1,所以返回

函数B   向下选 剩下2,1,1   2之前选过,不能继续选,选1,标记函数B中选1

剩下的和都不够5所以,只有一组。


 这样下来就可以保证,每个小决定的选择不会选相同的。

这个也最好是由大到小排序后,将某此选择序号向下一个函数传递,下一个函数从该序号向后找。

当然,不要忘了没有答案的情况判断(*^__^*) 


程序代码:

#include <iostream>#include <string.h>#include <algorithm>using namespace std;int arr[1001],jl[1001];bool vis[1001],isfind;int n,t;void dfs(int sum,int num,int k){    // 总和比t大,没必要继续找了    if(sum>t)   return;    int i;    // 第一个直接输出,第二个开始和+号配对输出    if(sum==t)    {        cout<<jl[0];        for(i=1;i<num;++i)            cout<<"+"<<jl[i];        cout<<endl;        // 记录有没有解,为输出NONE做铺垫        isfind=true;        return;    }    int tag=-1;    for(i=k;i<n;++i)    {        if(!vis[i] && tag!=arr[i])        {            jl[num]=arr[i];            vis[i]=1;            tag=arr[i];            dfs(sum+arr[i],num+1,i);            vis[i]=0;        }    }}// 由大到小排列bool cmp(int a,int b){    return a>b;}int main(){    int i;    while(cin>>t>>n)    {        if(!t && !n)    break;        for(i=0;i<n;++i)    cin>>arr[i];        memset(vis,0,sizeof(vis));        sort(arr,arr+n,cmp);        cout<<"Sums of "<<t<<":"<<endl;        isfind=false;        dfs(0,0,0);        if(!isfind) cout<<"NONE"<<endl;    }    return 0;}


1 0
原创粉丝点击