poj 3187 Backward Digit Sums

来源:互联网 发布:usb3.0端口 编辑:程序博客网 时间:2024/05/01 12:06
Backward Digit Sums
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 5389 Accepted: 3112

Description

FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N <= 10) in a certain order and then sum adjacent numbers to produce a new list with one fewer number. They repeat this until only a single number is left. For example, one instance of the game (when N=4) might go like this: 

    3   1   2   4      4   3   6        7   9         16
Behind FJ's back, the cows have started playing a more difficult game, in which they try to determine the starting sequence from only the final total and the number N. Unfortunately, the game is a bit above FJ's mental arithmetic capabilities. 

Write a program to help FJ play the game and keep up with the cows.

Input

Line 1: Two space-separated integers: N and the final sum.

Output

Line 1: An ordering of the integers 1..N that leads to the given sum. If there are multiple solutions, choose the one that is lexicographically least, i.e., that puts smaller numbers first.

Sample Input

4 16

Sample Output

3 1 2 4

Hint

Explanation of the sample: 

There are other possible sequences, such as 3 2 1 4, but 3 1 2 4 is the lexicographically smallest.

Source

USACO 2006 February Gold & Silver

起初毫无思路,,后来慢慢想出了DFS,,有两个很关键的地方,,一个是由最底层求出最顶的一个数的时候,,是需要用到
杨辉三角的思想的,,第二点,,也非常非常重要!!要按最小字典序输出,,其实只要从小到大枚举,,一旦找到符合条件的
退出就可以了,,这点非常关键,,不然再写个字典序函数会增加许多难度的,,p[I]表示第i位所放置的数字,,后来学习一下
STL内部的一个全排列函数,,自己多想多想。。。。  
解法1:暴力搜索,注意一旦找到解立即退出,,204ms
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,sum,a[12][12],p[12],flag;
int yang()
{
    a[1][0]=n;
    for(int i=1;i<=n;i++)
         a[1][i]=p[i];
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=a[i-1][0]-1;j++)
         a[i][j]=a[i-1][j]+a[i-1][j+1];
        a[i][0]=a[i-1][0]-1;
    }
    return a[n][1];
}
int dfs(int cur)
{
      if(!flag)
         return 0;
      if(cur==n+1)
     {
        int toa=yang();
        if(toa==sum)
        {
            flag=0;
             printf("%d",p[1]);
         for(int i=2;i<=n;i++)
            printf(" %d",p[i]);
         printf("\n");
        }
        return 0;
     }
     for(int i=1;i<=n;i++)
        {
        int ok=1;
        for(int j=1;j<cur;j++)
             if(p[j]==i)
        {
            ok=0;
            break;
        }
           if(ok)
           {
             p[cur]=i;
             dfs(cur+1);
             p[cur]=-1;
           }
        }
     return 0;
}
int main()
{
    while(~scanf("%d %d",&n,&sum))
    {
         flag=1;
         memset(p,0,sizeof(p));
         dfs(1);
    }
    return 0;
}


解法二:STLnext_permutation函数调用+优化后的杨辉三角   79ms
需要注意的是next_permutation()函数是求出当前字典序的下一个,,所以
while(next_permutation(a+1,a+n+1));不能写在开头,,,因为next_permutation(a+1,a+n+1))函数只有在当前字典序是最大时才会
返回false,,所以放在开头的话已经进行了一次排序了,所以从1--n这个字典序直接会被跳过
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int n,sum;
    while(~scanf("%d %d",&n,&sum))
    {
       int a[13],b[13];
       for(int i=1;i<=n;i++)
           a[i]=i;
       do{
            for(int j=1;j<=n;j++)
                  b[j]=a[j];
           int temp=n;
           while(temp>1)
           {
                for(int j=1;j<=temp-1;j++)
                    b[j]+=b[j+1];
                temp--;
           }//杨辉三角优化

            if(b[1]==sum)
            {
                 for(int i=1;i<=n-1;i++)
                    printf("%d ",a[i]);
                 printf("%d \n",a[n]);
                 break;
            }
       }while(next_permutation(a+1,a+n+1));
    }
    return 0;
}
0 0