POJ 3187 Backward Digit Sums

来源:互联网 发布:网络直播电视 编辑:程序博客网 时间:2024/06/03 21:55

题意:求出n个数使它们的和等于sum,若有多种答案,输出字典序小的那个

          3      1      2     4

              4     3     6

                  7     9

                    16                           输入4和16,输出3 1 2 4

解题思路1:将数字1~n用一维数组存起来,用next_permutation(a,a+n)函数进行全排列,直接输出第一个符合条件的即可,因为全排列是按照字典序进行的排列,第一个符合条件的一定是所有符合条件中字典序最小的那一个。注意要特判1 2 3 ... n的情况。

代码:


#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <cstdio>using namespace std;int n,sum;int a[15],p[15];int main(){    while(cin>>n>>sum)    {        for(int i=0; i<n; i++)        {            a[i]=i+1;        }        int k=n;//判断1 2 3 4 ... n这种情况符不符合条件        for(int i=0; i<n; i++)        {            p[i]=a[i];        }        while(k>1)        {            for(int i=0; i<n-1; i++)            {                p[i]+=p[i+1];            }            k--;        }        if(p[0]==sum)        {            for(int i=0; i<n; i++)            {                if(i)cout<<" "<<a[i];                else cout<<a[i];            }            cout<<endl;            continue;        }        while(next_permutation(a,a+n))//对1 2 3 4 ... n进行全排列        {            int k=n;            for(int i=0; i<n; i++)            {                p[i]=a[i];            }            while(k>1)            {                for(int i=0; i<n-1; i++)                {                    p[i]+=p[i+1];                }                k--;            }            if(p[0]==sum)            {                for(int i=0; i<n; i++)                {                    if(i)cout<<" "<<a[i];                    else cout<<a[i];                }                cout<<endl;                break;            }        }    }    return 0;}

解题思路2:深搜dfs.也是要先将1~n个数进行全排列存到另一个数组中,然后判断是否符合条件,用dfs进行的全排列也是按照字典序排的,所以第一个符合条件的也是字典序最小的那一个,输出字典序最小的这个解然后就直接返回不再往下进行了,用flag做标记。但是这种方法比上一种慢

代码:

#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <cstdio>using namespace std;int n,sum,flag;int a[15],p[15],b[15],vis[15];int solve(int k){    for(int i=0;i<n;i++)p[i]=b[i];    while(k>1)    {        for(int i=0;i<n-1;i++)        {            p[i]+=p[i+1];        }        k--;    }    if(p[0]==sum)return 1;    return 0;}void dfs(int cur){    if(cur==n)    {        if(solve(n))        {            flag=1;            for(int i=0;i<n;i++)            {                if(i)cout<<" "<<b[i];                else cout<<b[i];            }            cout<<endl;            //return ;返回上一层,会输出多组解,所以要用flag标记一下,找到一组解后直接返回        }    }    if(flag)return ;//找到字典序最小的解就返回,不再进行dfs了    else    {        for(int i=0;i<n;i++)        {            if(!vis[i])            {                b[cur]=a[i];                vis[i]=1;                dfs(cur+1);                vis[i]=0;            }        }    }}int main(){    while(cin>>n>>sum)    {        for(int i=0;i<n;i++)        {            a[i]=i+1;        }        memset(vis,0,sizeof(vis));        flag=0;        dfs(0);    }    return 0;}



原创粉丝点击