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

本文讨论了如何通过已知的杨辉三角的最后一行数值和三角形的高度,推算出初始行数的计算方法。包括杨辉三角的性质、公式及对应的代码实现,并通过DFS方法解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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里。

有了Ck那么即使题目中的初始数字不为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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值