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;

}

 

 

你可能感兴趣的:(HDU)