(DFS、全排列)POJ-3187 Backward Digit Sums

题目地址

简要题意:

  输入两个数n和m,分别表示给你1——n这些整数,将他们按一定顺序摆成一行,按照杨辉三角的计算方式进行求和,求使他们求到最后时结果等于m的排列中字典序最小的一种。

思路分析:

  不难推得第一行为n个数a1\a2\……\an时求得的和为i=0∑n-1 ai*(n-1Ci) 根据此公式,考虑到数据量比较小,只需要将原本按递增顺序依次排列好的1——n按next_permutation给出的递增全排列顺序逐个代入,如果结果与m相等就停止循环即可。

参考代码:

  

 1 #include<stdio.h>
 2 #include<cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 int fact[11],ncr[11][11],b[10]={1,2,3,4,5,6,7,8,9,10};//先将1——n准备好
 8 int main()
 9 {
10     int i,j;
11     fact[0]=fact[1]=1;//由于数据小,先预处理,计算好阶乘
12     for(i=2;i<=10;i++)
13     {
14         fact[i]=fact[i-1]*i;
15     }
16     for(i=1;i<=10;i++)
17     {
18         for(j=0;j<=i/2;j++)
19         {
20             ncr[i][j]=ncr[i][i-j]=(fact[i]/(fact[j]*fact[i-j]));//计算各个组合数
21         }
22     }
23     int n,he,de;
24     scanf("%d%d",&n,&he);
25     n--;
26     if(n==0)
27         printf("1\n");
28     else{
29             de=0;
30         for(i=0;i<=n;i++)//先判断一下初始递增的情况是否就满足,后面调用next_permutation貌似就直接从第二项开始了
31         {
32             de+=b[i]*ncr[n][i];
33         }
34         if(de==he)
35             {
36                 for(i=0;i<=n;i++)
37                 {
38                     printf("%d ",b[i]);
39                 }
40                 return 0;
41             }
42     while(next_permutation(b,b+n+1))//全排列
43     {
44         de=0;
45         for(i=0;i<=n;i++)
46         {
47             de+=b[i]*ncr[n][i];
48         }
49         if(de==he)
50             {
51                 for(i=0;i<=n;i++)
52                 {
53                     printf("%d ",b[i]);
54                 }
55                 break;
56             }
57     }
58     printf("\n");
59     }
60     return 0;
61 }

 

posted @ 2016-12-05 22:02  perplex  阅读(221)  评论(0编辑  收藏  举报