HDU 1258 Sum It Up(Dfs)

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

题意:sum  n    n个数,输出所有和为sum的组合,要非递增且不能重复如第三个样例:本来可以有多个50+50+50+50+50+50+25+25+25+25,但是只输出了一个

这里有两点:1~怎么输出非递增的组合。。。。由于他输入就按非递增的了。。。所以我Dfs的for()从最后一个被用的下一位开始找。。。。保证下一个数是在目前最后一个被用的数字的后面。。。

2~怎么判重,本来可以求SUM然后从低位像a+b*sum+c*sum*sum的形式Hash,但是1000^12太大了。。。,由于最多只有12个数,且每个数字最多两位,所以我想到把数字Hash成字符串然后用set来判重。。。。

代码:

#include <iostream>
#include <string>
#include <set>
using namespace std;

const int  M = 100 + 10;

set <string> s;
int save[M];
int ans[M];
bool used[M];
int sum;
int n;
int flag;


void Dfs(int now, int now_sum)
{


    if (now_sum == sum)
    {
        string str;
        for (int i = 1; i <= now; i++)//把这些数字Hash成字符串,用来判重
        {
            str += (ans[i] / 10) + '0';
            str += ans[i] % 10 + '0';
        }

        if (s.find(str) == s.end())
        {
            s.insert(str);
            flag = 1;
            for (int i = 1; i <= now; i++)
            {
                printf(i == 1 ? "%d" : "+%d", ans[i]);
            }
            puts("");
        }
        return ;
    }
    int j;
    for (j = n; j >= 1 && !used[j]; j--);//找最后一个被用的位置

    for (int i = j + 1; i <= n; i++)//从最后一个被用的下一位开始,保证非递增
    {
        if (!used[i] && now_sum + save[i] <= sum)
        {
            used[i] = 1;
            ans[now+1] = save[i];
            Dfs(now + 1, now_sum + save[i]);
            used[i] = 0;
        }
    }
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w",stdout);
    while (~scanf("%d%d", &sum, &n), n)
    {
        printf("Sums of %d:\n", sum);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", save + i);
        }

        flag = 0;
        memset(used, 0, sizeof(used));
        s.clear();
        Dfs(0, 0);
        if (flag == 0)
        {
            puts("NONE");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qiufeihai/p/2679310.html