P1118 [USACO06FEB]数字三角形`Backward Digit Su`…(搜索 + 杨辉三角)

题目链接:https://www.luogu.com.cn/problem/P1118

思路:

首先根据每个数字出现的次数就是杨辉三角上的值,所以ans = (numi×i)。

然后搜索,最先搜出的ai序列即是结果,然后输出就好了。

注意减枝,记录当前出现的编号之和为tp,当前求出的结果为sm,1~n之和为pp,如果pp-tp > sum - sm就不行直接返回。

(杨辉三角太久不用都生疏了,竟然一开始没想到。)

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 55;
bool vis[N] = {false};
int a[N][N] = {0},sum,n,pp,b[N];
bool fg = false;
void dfs(int rt,long long sm,int tp)
{
    if(rt == n && sm == sum)
    {
        fg = true;
        for(int i=1;i<=n;i++)
        {
            if(i>1) printf(" "); printf("%d",b[i]);
        }
        return ;
    }
    if(rt == n) return ;
    if(sm >= sum || sum - sm < pp-tp || fg == true) return ; //减枝
    for(int i=1;i<=n;i++)
    {
        if(vis[i] == true) continue;
        vis[i] = true;
        b[rt+1] = i;
        dfs(rt+1,sm+a[n][rt+1]*i,tp+i);
        if(fg == true) return ;
        vis[i] = false;
    }
}
int main(void)
{
    a[1][1] = 1;
    for(int i=2;i<=12;i++)
    {
        for(int j=1;j<=i;j++) a[i][j] = a[i-1][j-1] + a[i-1][j];
    }
    scanf("%d%d",&n,&sum);
    //for(int i=1;i<=n;i++) printf("%d ",a[n][i]); printf("\n");
    pp = 0;
    for(int i=1;i<=n;i++) pp += i;
    dfs(0,0,0);
    return 0;
}
发布了438 篇原创文章 · 获赞 16 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/103764356