洛谷OJ P1118 数字三角形游戏 解题报告

洛谷OJ P1118 数字三角形游戏 解题报告

by MedalPluS

  题目描述

  有这么一个游戏:
写出一个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行,为字典序最小的那个答案

  规模

对于40%的数据,n≤7;
对于80%的数据,n≤10;
对于100%的数据,n≤12,sum≤12345,且保证一定有解。

  分析

拿到题目就有一种暴搜的想法,我们枚举1~n的全排列,然后逐个试

结果就TLE了。。60分

然后想了想,每次试的时候n2有点耗时,然后又发现对于第1层的数=∑ai*cni (ai表示枚举的数列 cij表示杨辉三角第n行第i列)

然后还是TLE了。。80分

觉得STL太慢了,手写了个DFS,再加了个可行性剪枝

结果居然WA90了。。

发现杨辉三角写挫了。。

要自责。。。

  代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int maxn=13;
 8 
 9 int a[maxn],c[maxn][maxn],n,sum;
10 bool used[maxn];
11 
12 void dfs(int i,int sum){
13     if(sum<0)return;
14     if(i>n){
15         if(sum>0)return;
16         for(int j=1;j<=n;j++)printf("%d ",a[j]);
17         exit(0);
18     }
19     for(int j=1;j<=n;j++)
20       if(!used[j]){
21           used[j]=true;
22           a[i]=j;
23         dfs(i+1,sum-j*c[n][i]);
24         used[j]=false;
25       }
26 }
27 
28 int main(){
29     cin>>n>>sum;
30     int i,j,res=0;
31     for(i=1;i<=n;i++)a[i]=i;
32     for(i=1;i<=n;i++)c[i][i]=c[i][1]=1;
33     for(i=3;i<=n;i++)
34       for(j=2;j<=i;j++)
35         c[i][j]=c[i-1][j]+c[i-1][j-1];
36     memset(used,false,sizeof(used));
37     dfs(1,sum);
38     return 0;
39 }

 

 

 

posted @ 2015-05-17 00:48  MedalPluS  阅读(778)  评论(0编辑  收藏  举报