洛谷P1118 数字三角形

324 阅读1分钟
题目链接: www.luogu.com.cn/problem/P11…


总的思路就是DFS,不过需要注意剪枝,否则会超时。

手写了a, ab, abc, abcd后发现,最后的倒三角形和的系数是有规律的,看了题解才想起来就是杨辉三角形的第n行,由此可以先把第n行的杨辉三角打表打出来,然后DFS每进入一层就判断当前结果是否已经超出sum,超出就直接返回了。

杨辉三角的第n行第m个数 = C(n-1,m-1),可以根据组合数公式算,这题n不算大,可以硬算。不过看了题解还可以这样算:C(n,r) = [(n-r+1) / r] * C(n, r-1); 具体的可以自己推导一下。这样就可以根据前一个数推出后一个数,起始边界是1,而且杨辉三角是对称的,算一半就可以了。


AC代码:

#include<iostream>
using namespace std;

int n, sum;
int a[15];
int yanghui[15];
int vis[15];
void dfs(int cur);
int judge(int cnt);
bool flag = false;

int main(void)
{
    cin >> n >> sum;
    
    //构造第n行的杨辉三角
    yanghui[1] = yanghui[n] = 1;
    for(int i = 2; i <= n/2; i++)
        yanghui[i] = yanghui[n+1-i] = (n-i+1) * yanghui[i-1] / (i-1);
    if(n & 1 && n != 1)
        yanghui[n/2+1] = (n/2+1) * yanghui[n/2] / (n/2);

    dfs(1);
    return 0;
}

void dfs(int cur)
{

    if(cur == n+1){
        if(judge(n) == sum){
            for(int i = 1; i < n; i++)
                cout << a[i] << " ";
            cout << a[n] << endl;

            flag = true;
            return;
        }
    }

    if(flag)
        return;
    if(judge(cur-1) > sum) 
        return;

    for(int i = 1; i <= n; i++)
    {
        if(flag)
            return;
        
        if(vis[i])  
            continue;

        a[cur] = i;
        vis[i] = 1;
        dfs(cur+1);
        vis[i] = 0;
    }
}

int judge(int cnt)
{
    int res = 0;
    for(int i = 1; i <= cnt; i++)
        res += yanghui[i] * a[i];
    return res;
}