luogu P1118 [USACO06FEB]数字三角形`Backward Digit Su`…

luogu P1118 [USACO06FEB]数字三角形`Backward Digit Su`…_第1张图片

analysis

开始用了一个全排列的算法,n=12算下来会爆炸,于是就用了一个函数来求中间的数列的值来可行性剪枝,函数n^2,结果剪了枝还是没什么用
后面推了下公式,发现对于4个数a,b,c,d来说,最后的N=a+3b+3c+d,对于5个数a,b,c,d,e来说,最后的N=a+4b+6c+4d+e,这个时候隐隐约约觉得数的位置和其系数之间有关系,若可以通过位数来确定其系数的话就不用N^2求和了
殊不知这就是一个杨辉三角,自己还是太弱了啊
预处理一下杨辉三角然后剪两下枝就好了

code

#include
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a
#define ll long long
#define db double
int n,SUM;
const int maxn=12+10;
bool vis[maxn];
int permulate[maxn];
int yhsj[maxn][maxn];
template<typename T>void read(T &x){
    x=0;char r=getchar();T neg=1;
    while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
    while(r>='0'&&r<='9'){x=(x<<3)+(x<<1)+r-'0';r=getchar();}
    x*=neg;
}
inline int _SUM(register int _n){
    if(_n==0)return 0;
    int _sum=0;
    loop(i,1,_n)_sum+=yhsj[n][i]*permulate[i];
    return _sum;
}
void dfs(register int pos,register int w){
    if(w>SUM)return;
    if(pos>n){
        if(_SUM(n)==SUM){
        	for(register int i=1;i<=n;++i)printf("%d ",permulate[i]);
        	exit(0);
        }
        return;
    }
    loop(_i,1,n){
        if(vis[_i])continue;
        //if(sum+i+permulate[pos-1]>SUM)continue;
        permulate[pos]=_i;
        if(_SUM(pos)>SUM)continue;
        vis[_i]=true;
        dfs(pos+1,w+_i*yhsj[n][pos]);
        vis[_i]=false;
    }
}
inline void pre(){
    yhsj[1][1]=1;
    loop(i,2,n){
        loop(j,1,i){
            yhsj[i][j]=yhsj[i-1][j]+yhsj[i-1][j-1];
        }
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("datain2.txt","r",stdin);
    #endif // ONLINE_JUDGE
    read(n),read(SUM);clean(yhsj,0);
    clean(vis,0);clean(permulate,0);
    pre();
    dfs(1,0);
    return  0;
}

你可能感兴趣的:(搜索)