洛谷P1118 数字三角形游戏

来源:互联网 发布:刻碟用什么软件 编辑:程序博客网 时间:2024/06/06 19:29
洛谷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 }

 

0 0