洛谷P1118 数字三角形游戏

洛谷1118 数字三角形游戏

题目描述

有这么一个游戏:
写出一个1~N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置。下面是一个例子:
    3   1   2   4
      4   3   6
        7   9
         16
最后得到16这样一个数字。
现在想要倒着玩这样一个游戏,如果知道N,知道最后得到的数字的大小sum,请你求出最初序列a[i],为1~N的一个排列。若答案有多种可能,则输出字典序最小的那一个。

输入输出格式

输入格式:

两个正整数n,sum。

输出格式:

输出包括1行,为字典序最小的那个答案。
当无解的时候,请什么也不输出。(好奇葩啊)

输入输出样例

输入样例#1:

4 16

输出样例#1:

3 1 2 4

说明

对于40%的数据,n≤7;
对于80%的数据,n≤10;
对于100%的数据,n≤12,sum≤12345。

【思路】

  Dfs+杨辉三角。

  以题目数据为例:16=7+9=4+3+3+6=3+1+1+2+1+2+2+4=1*3 + 3*1 + 3*2 + 1*4

  所以可以推出公式sum=∑ Yni*Ai 

  状态包括深度与和,知道了公式可以剪去 和 超过sum的搜索。

【代码】

 1 #include<iostream>
 2 #include<cstdlib>
 3 using namespace std;
 4 
 5 const int maxn = 14;
 6 
 7 int n,M;
 8 int A[maxn],vis[maxn];
 9 int yn[maxn];
10 
11 void get_yn() {
12     for(int i=0;i<n;i++){
13        yn[i]=1;
14        for(int j=i/2;j>0;j--) yn[j]=yn[i-j]=yn[j]+yn[j-1];
15     }
16 }
17 void dfs(int d,int sum) {
18     if(d==n && sum==M) {
19         for(int i=0;i<n;i++) cout<<A[i]<<" ";
20         exit(0);
21     }
22     if(sum>M) return ;
23     for(int i=1;i<=n;i++) if(!vis[i]) {
24         vis[i]=1;
25         A[d]=i;
26         dfs(d+1,sum+yn[d]*i);
27         vis[i]=0;
28     }
29 }
30 
31 int main() {
32     ios::sync_with_stdio(false);
33     cin>>n>>M;
34     get_yn();
35     dfs(0,0);
36     return 0;
37 }
原文地址:https://www.cnblogs.com/lidaxin/p/4860572.html