[USACO06FEB]Backward Digit Sums G/S (DFS&杨辉三角)
思路:利用DFS或者next_permutation 再稍加剪枝即可。具体细节见代码。
DFS代码
#include<bits/stdc++.h>
using namespace std;
int n,sum,c[12],ans[13],vis[13];// c[]计算 C(n-1,i) vis[i]表示i是否被用
bool dfs(int cnt,int tot){//cnt:当前个数,tot:当前总和
//printf("cnt=%d,tot=%d\n",cnt,tot);
if(tot>sum) return 0;
if(cnt==n) return tot==sum;
for(int i=1;i<=n;i++)
if(!vis[i])
{
vis[i]=1;
ans[cnt+1]=i;
if(dfs(cnt+1,tot+c[cnt]*i)) return 1;
vis[i]=0;
}
return 0;
}
int main(){
cin>>n>>sum;
c[0]=c[n-1]=1;//初始化
for(int i=1;i*2<n;i++) //组合数
c[i]=c[n-1-i]=c[i-1]*(n-i)/i;
if(dfs(0,0)) for(int i=1;i<=n;i++) printf(i==n?"%d\n":"%d ",ans[i]);
return 0;
}
next_permutation代码
#include<bits/stdc++.h>
using namespace std;
int a[13],c[13],n,sum,tot;
int main(){
cin>>n>>sum;
c[0]=c[n-1]=1;
for(int i=1;i*2<n;i++) c[i]=c[n-1-i]=c[i-1]*(n-i)/i;
for(int i=1;i<=n;i++) a[i]=i;
do{
tot=0;
for(int i=1;i<=n;i++)
{
tot+=a[i]*c[i-1];
if(tot>sum){
sort(a+i,a+n+1,greater<int>());//从第i开始增大的字典序肯定不行,将i到最后一位从大到小排序,使第i-1位增大一位再继续
break;
}
}
if(tot==sum){
for(int i=1;i<=n;i++)
printf(i==n?"%d\n":"%d ",a[i]);
break;
}
}while(next_permutation(a+1,a+n+1));
return 0;
}