HDU 1258 Sum It Up

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

一道以前做过的搜索题.解法就是排序后搜索.

题目要求相同的解只输出一次.

记得以前看过别人的解法是搜索时加个限定条件,一时没想起来,所以自己乱搞.

所谓乱搞就是用哈希了,用累加的序列构造哈希表.嘛,虽然做起来我也觉得有点运气成分.(因为构造哈希的算法是乱来的)

没有验证过的哈希算法经不起推敲,也许数据强点我就挂了..还是贴代码吧,这次写丑了,懒得改.

#include <iostream>
#include <algorithm>
using namespace std;
int num[12];
int vis[12];
int hash[1000];
int sum,n,pre_t = 1;
int isNone = 1;
void DFS(int pos,int temp)
{

    if(temp == sum)
    {
        int t = 1;
        for(int i=0;i<n;i++)
        {
            if(vis[i] != -1)
            {
                if(num[i] < 11)
                    t = (t * num[i] + 11) % 1000 ;
                else if( num[i] < 33)
                    t = (t * num[i] * num[i] + 11) % 1000;
                else if( num[i] < 71)
                    t = (t * num[i] * t + 111) % 1000;
            }
        }
        if(!hash[t])
        {
            bool isStart = 1; 
            for(int i=0;i<n;i++)
            {
                if(vis[i]!=-1) 
                {
                    if(isStart)
                    {
                        cout<<num[i];
                        isStart = 0;
                        isNone = 0;
                    }
                    else
                        cout<<"+"<<num[i];
                }
            }
            cout<<endl;
            hash[t] = 1;
        }
        return;
    }
    if(pos>=n) return;
    for(int i=pos;i<n;i++)
    if(temp + num[i]<= sum)
    {
        vis[i] = 1;
        DFS(i+1,temp+num[i]);
        vis[i] = -1;
    }
}
bool cmp(int a,int b)
{
      return a>b;   //升序排列,如果改为return a>b,则为降序
}
int main(int argc, const char *argv[])
{
    freopen("input.txt","r",stdin);

    while(cin>>sum>>n&&(sum+n))
    {
        memset(vis,-1,sizeof(vis));
        memset(hash,0,sizeof(hash));
        for(int i=0;i<n;i++)
            cin>>num[i];
        sort(num,num+n,cmp);
        printf("Sums of %d:
",sum);
        DFS(0,0);
        if(isNone)
        {
            printf("NONE
");
        }
        isNone = 1;
    }
    return 0;
}

另附上别人的参考程序,此为正解.

#include <iostream>
#include <algorithm>
using namespace std;
bool vis[100],flag;
int a[100],n,m,top;
int ans[100];
void print(int top)
{
    cout<<ans[0];
    for(int i=1;i<top;i++)
        cout<<"+"<<ans[i];
    cout<<endl;
}
void BFS(int sum,int pos)
{
    for(int i=pos;i<m;i++)
    {
        int now=sum+a[i];
        if(now<n)
        {
            vis[i]=true;
            ans[top++]=a[i];
            BFS(now,i+1);
            vis[i]=false;
            --top;
        }
        else if(now==n)
        {
            ans[top++]=a[i];
            print(top);
            --top;
            flag=1;
        }
        while(a[i]==a[i+1]) ++i;//此处亮点,使接下来不再出现以相同的a[i]为第top个数的序列,避免了重复.
    }
}

bool cmp(const int &a,const int &b)
{
    return a>b;
}

int main()
{
//    freopen("test.txt","r",stdin);
    int i;
    while(cin>>n>>m,n)
    {
        flag=0;
        int sum=0;
        for(i=0;i<m;i++)
        {
            cin>>a[i];
            sum+=a[i];
        }
        cout<<"Sums of "<<n<<":"<<endl;
        if(sum<n)
        {    cout<<"NONE"<<endl;continue;}
        sort(a,a+m,cmp);
        BFS(0,0);
        if(!flag) cout<<"NONE"<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/destino74/p/3316012.html