POJ 3187 Backward Digit Sums (杨辉三角,穷竭搜索,组合数,DFS)

http://poj.org/problem?id=3187

将一行数按杨辉三角的规则计算为一个数,已知最后那个数和三角形的高度,求最初的那行数。

杨辉三角前10行:

                 
1

                 
               
1

 
1

               
             
1

 
2

 
1

             
           
1

 
3

 
3

 
1

           
         
1

 
4

 
6

 
4

 
1

         
       
1

 
5

 
10

 
10

 
5

 
1

       
     
1

 
6

 
15

 
20

 
15

 
6

 
1

     
   
1

 
7

 
21

 
35

 
35

 
21

 
7

 
1

   
 
1

 
8

 
28

 
56

 
70

 
56

 
28

 
8

 
1

 

1

 
9

 
36

 
84

 
126

 
126

 
84

 
36

 
9

 
1

杨辉三角第n层第k个数记为Ckn那么=n!/[k!(n-k)!]=n * (n
– 1)…*(n – k + 1) / k!

对应着下面这段代码

int c(int n, int k)
{
    int result = 1;
    for (int i = 0; i < k; ++i)
    {
        result = result * (n - i) / (i + 1);
    }

    return result;
}

上面做了一个简化,因为原始的式子里面分子分母的项数相等所有写进一个loop里。

有了Ckn 那么即使题目中的初始数字不为1,只要乘上这个系数Ckn就行了。

#include <iostream>

#include <string>

#include <algorithm>

using namespace std;

int c(int n, int k)

{

    int result = 1;

    for (int i = 0; i < k; ++i)

    {

        result = result * (n - i) / (i + 1);

    }

    return result;

}

int main(int argc, char *argv[])

{

    int N, Sum;

    cin >> N >> Sum;

    int line[16];

    int i = 0;

    for (; i < N; ++i)

    {

        line[i] = i + 1;

    }

    do

    {

        int result = 0;

        for (i = 0; i < N; ++i)

        {

            result += c(N - 1, i) * line[i];

        }

        if (result == Sum)

        {

            break;

        }

    while (next_permutation(line, line + N));

    copy(line, line + N, ostream_iterator<int>(cout, " "));

    return 0;

}

DFS的方法:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define PI 3.1415926

bool visit[15];
int a[15],b[15];
int N, sum;

bool per(int k){
    if(k == (N+1)){
        int i,j;
        for(i=1; i<=N; ++i)
            b[i] = a[i];
        for(i=1; i<N; ++i){
            for(j=1; j<=N-i; ++j){
                b[j] = b[j]+b[j+1];
            }
        }
        if(b[1] == sum){
            for(i=1; i<=N; ++i)
                printf("%d ", a[i]);
            printf("\n");
            return true;
        }
        return false;
    }

    int i;
    for(i=1; i<=N; ++i){
        if(!visit[i]){
            visit[i] = true;
            a[k] = i;
            if(per(k+1))
                return true;
            visit[i] = false;
        }
    }
    return false;
}

int main(){
    #ifdef LOCAL
        freopen("1.in","r", stdin);
    #endif

    while(~scanf("%d%d", &N, &sum)){
        memset(visit, false, sizeof(visit));
        per(1);
    }
    return 0;
}

时间: 2024-12-06 11:18:12

POJ 3187 Backward Digit Sums (杨辉三角,穷竭搜索,组合数,DFS)的相关文章

POJ 3187 Backward Digit Sums(next_permutation)

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

POJ3187Backward Digit Sums[杨辉三角]

Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6350   Accepted: 3673 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 ad

poj 3187 Backward Digit Sums(穷竭搜索dfs)

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

POJ 3187 Backward Digit Sums

http://poj.org/problem?id=3187 穷竭搜索 全排列 然后按规则求和 排列之前先按升序排序 这样可以保证第一个和为k的就是符合最小序列的结果 1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 5 using namespace std; 6 7 int sum(int a[], int n) 8 { 9 int s[11]; 10 for (int i = 0

POJ 3187 Backward Digit Sums 题解 《挑战程序设计竞赛》

题目:POJ 3187 思路: 这道题很简单,用next_permutation枚举1~N的所有排列,然后依次相加,判断最后的和是否等于sum,是的话则break,即为字典序最前的. 1 #include <iostream> 2 #include <algorithm> 3 4 using namespace std; 5 6 int n; 7 int sum; 8 int mycase[11][11]; 9 10 int main() { 11 cin >> n &

POJ 3187 Backward Digit Sums (dfs,杨辉三角形性质)

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. Fo

POJ 题目Backward Digit Sums(next_permutation)

Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4807   Accepted: 2772 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 ad

杨辉三角,二项式系数,组合数,斐波那契数列

古人就是厉害,在此%杨辉大佬,这个杨辉三角真的是好厉害啊. 杨辉三角 杨辉三角,是二项式系数在三角形中的一种几何排列.在欧洲,这个表叫做帕斯卡三角形.帕斯卡(1623----1662)是在1654年发现这一规律的,比杨辉要迟393年,比贾宪迟600年. 排列信息: 杨辉三角有多种重要的性质. 概述: 前提:每行端点与结尾的数为1. 每个数等于它上方两数之和. 每行数字左右对称,由1开始逐渐变大. 第n行的数字有n项. 第n行数字和为2n-1. 第n行的m个数可表示为 C(n-1,m-1),即为从

Enum:Backward Digit Sums(POJ 3187)

反过来推 题目大意:就是农夫和这只牛又杠上了(怎么老是牛啊,能换点花样吗),给出一行数(从1到N),按杨辉三角的形式叠加到最后,可以得到一个数,现在反过来问你,如果我给你这个数,你找出一开始的序列(可能存在多个序列,输出字典序最小的那个). 这一题首先你要看懂原文的那个1到N是什么意思,就是那一行数只能是1到N,而不是1到10(我一开始犯了这个愚蠢的错误,导致枚举到风扇呼呼的转),如果是这样给你,那么这道题就很简单啦,就直接是用next_permutation枚举所有的序列就可以了,然后找出字典