HDU 1258-Sum It Up

来源:互联网 发布:淘宝能卖军用品吗 编辑:程序博客网 时间:2024/05/16 17:52

Sum It Up

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6853    Accepted Submission(s): 3606


题目链接:点击打开链接


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


题意:给你两个数 t 和 n ,然后有 n 个数,让你找出 n 序列里的元素和为 t 的情况,每组情况只能用一次列表里出现的元素,然后 t 是不大于1000的正整数(因为我当时考虑如果 t 为 0 的情况,这就是读题不仔细的后果,浪费时间和精力),拿第一组数据来加深说明题意。

4 6 4 3 2 2 1 1
代表 t = 4;n = 6;然后输入六个数,这种情况下符合题意的情况有
4
3+1
2+2
2+1+1
而不能出现重复的组合,比如说元素有一个 3 ,两个 1 ,但是呢,只输出一次 3+1 ,还有就是之所以没有出现 1+1+1+1+1 的情况,是因为一个序列只有两个 1,。
题意中说按递减的顺序输出,但我第一次忘排序也是对的,最好还是读清题意,按题意来。


分析:
感觉 dfs 题还是的清楚递归思想,以及递归过程是怎样实现的就好办,这题有一个点很重要,就是你得 定义一个变量来存放上次递归时的值,大家称之为剪枝,我定义的是 pre 来保存该值,但是 pre 不能定义为全局变量,否则会多输出重复的。



#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;int s[20],n,t,bj,cun[20];bool cmp(int m,int n){    return m > n;}void dfs(int x,int sum,int z){    if(sum==0)//找到一组就输出一组,再回溯上一层重新找下一组    {        bj=1;//如果有找到加和为 t 的序列就取消标记        for(int i=0;i<z;i++)        {            if(i)                printf("+%d",cun[i]);            else                printf("%d",cun[i]);        }        printf("\n");        return ;    }    else    {        int pre=-1;        for(int i=x;i<n;i++)        {            if(sum>=s[i]&&s[i]!=pre)/如果该元素小于 sum 并且并不等于上一层递归的元素值,就再继续            {                pre=s[i];                cun[z]=s[i];                dfs(i+1,sum-s[i],z+1);            }        }    }}int main(){   while(~scanf("%d %d",&t,&n))   {       if(t==0&&n==0)            break;        bj=0;        for(int i=0;i<n;i++)            scanf("%d",&s[i]);       printf("Sums of %d:\n",t);       sort(s,s+n,cmp);//对该数组排序,题中有要求       dfs(0,t,0);       if(!bj)//如果没有找到等于 t 的加和就输出NONE            printf("NONE\n");   }    return 0;}


 

原创粉丝点击