SSL-ZYC 洛谷 P1118 数字三角形

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


思路:
注:这道题不是那道简单的DP数字金字塔!
虽然这道题还是很简单。。。

我们观察一下,就可以发现:

n=2,最终得a+b

n=3,得a+2b+c

n=4,得a+3b+3c+d

n=5,得a+4b+6c+4d+e

每个字母的系数为杨辉三角第行的数!


那么这道题的方法就很明确了:
1.由于n<=13,所以可以暴力求杨辉三角。
2.DFS,搜索。


代码:

#include <cstdio>
#include <iostream>
using namespace std;

int n,ok,m,a[101][101],o[101],t[101];

void dfs(int x,int k)  //DFS搜索
{
    if (x>n)
    {
        if (k==m)  //和正好为m
        {
            for (int i=1;i<=n;i++) printf("%d ",o[i]);  
            ok=1;
        }
        return;
    }
    if (k>m) return;  //剪枝
    for (int i=1;i<=n;i++)
    {
        if (t[i]==0)  //没有用过这个数
        {
           t[i]=1;
           o[x]=i;
           dfs(x+1,k+i*a[n][x]);
           t[i]=0;
           o[x]=0;
        }
        if (ok==1) return;
    } 
}

int main()
{
    scanf("%d%d",&n,&m);
    a[0][1]=1;
    for (int i=1;i<=n;i++) 
     for (int j=1;j<=i;j++) 
      a[i][j]=a[i-1][j]+a[i-1][j-1];  //求杨辉三角
    dfs(1,0);     
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ssl_zyc/article/details/79837046
今日推荐