Poj 1564 Sum It Up

来源:互联网 发布:米拉奇战记无敌版软件 编辑:程序博客网 时间:2024/05/18 03:46
Sum It Up
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 7921 Accepted: 4065

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 x 1 , . . . , x n . 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 x 1 , . . . , x n 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 distinct; the same sum cannot appear twice.

Sample Input

4 6 4 3 2 2 1 15 3 2 1 1400 12 50 50 50 50 50 50 25 25 25 25 25 250 0

Sample Output

Sums of 4:43+12+22+1+1Sums of 5:NONESums of 400:50+50+50+50+50+50+25+25+25+2550+50+50+50+50+25+25+25+25+25+25

题意:给你一个和t 一个n,再给你n个整数让你从这些数中找出何为提的情况。#include <stdio.h>#include <iostream>#include <string.h>#include <algorithm>#define N 20using namespace std;int t, n, cnt;  //t表示目标和; n表示输入的整数的个数; cnt若是0表示没有找到方案,若是1表示找到了方案int a[N], b[N];  //a数组表示,要求存入的n个数;b数组表示答案的数组,数组的元素按顺序输出就是一种方案void dfs(int ai, int bi, int sum)   //ai表示在a数组中的下一个要加入b数组中的数下标值, bi是当前求b数组的长度,sum是当前的b数组个元素之和。{    if(sum > t)   //如果b数组的和以大于目标和t,则不用再往下找了,这种方案不适合;        return;    if(sum == t)   //满足题意的方案    {        cnt = 1;  //标记是否找到了方案,这样为判断是否输出"NONE"提供了依据;        for(int i = 0; i < bi; i++)  //方案的输出        {            if(i)            {                printf("+%d", b[i]);            }            else                printf("%d", b[i]);        }        cout << endl;        return;              //一定要有,(不然浪费时间,去运行下面的for循环了),既然这种情况都满足,就不必再往下找了,只有在sum小于t的情况才往下找    }    for(int i = ai; i < n; i++)     //由于sum小于t,继续往下找不断的添加b数组中的值,使其sum达到前两种情况,(这一小点是整个题目的核心)    {        b[bi] = a[i];    //往b数组中值,此时就可以看出为什么要传ai,bi这些下标参数;        dfs(i + 1, bi + 1, sum+a[i]);      //寻找下一个下标情况        while(a[i] == a[i + 1])   //这是排出重复的过程,(如果不懂为什么:首先考虑什么情况下上面一段dfs(i + 1, bi + 1, sum+a[i]) 执行结束,开始执行之一段?        {                        //只有在满足条件sum大于t 或者 sum等于t 才会dfs()函数返回,大于的情况的本来不适合则直接跳过所有相同的,这样可以省时间;等于的            i++;             //情况若不跳过,则这次dfs()深搜下去后的结果,不就与上次的相同了吗?所以去掉,跳过相同的。这里还有许多细节没有阐述,不再赘述多体会,加油)        }    }    return;}int cmp(int a,int b){    return a > b;}int main(){    while(~scanf("%d%d", &t, &n))    {        cnt = 0;        if(t == 0 && n == 0)            break;        for(int i = 0; i < n; i++)        {            scanf("%d", &a[i]);        }        sort(a, a+n, cmp);  //降序排列        printf("Sums of %d:\n", t);        dfs(0, 0, 0);        if(!cnt)        {            printf("NONE\n");        }    }    return 0;}