zoukankan      html  css  js  c++  java
  • SSLZYC 洛谷 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;
    }
  • 相关阅读:
    Linux pmap 工具
    bzoj 1060 贪心
    bzoj 1076 状压DP
    bzoj 1150 贪心
    bzoj 1412 最小割 网络流
    bzoj 3212 线段树
    bzoj 1942 斜率优化DP
    bzoj 1876 高精
    bzoj 1880 最短路
    斜率优化DP讲解
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313083.html
Copyright © 2011-2022 走看看