[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;
}