「USACO2006FEB」Backward Digit Sums

写出一个 1 至 N的排列 a_i ,然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少 1 ,直到只剩下一个数字位置。下面是一个例子:

3,1,2,4

4,3,6

7,9

16

最后得到 16这样一个数字。

现在想要倒着玩这样一个游戏,如果知道 N,知道最后得到的数字的大小 sum ,请你求出最初序列 a_i ,为 1至 N的一个排列。若答案有多种可能,则输出字典序最小的那一个。(注意:这里字典序指的是 1,2,3,4,5,6,7,8,9,10,11,12,而不是 1,10,11,12,2,3,4,5,6,7,8,9 )

输入

两个整数,n,sum(n<=12,sum<=10000)

输出

1~n的一个排列

样例

样例输入1

4 16

样例输出1

3 1 2 4

提示


3,2,1,4最后得到的和也为16,但是3,1,2,4字典序更小

一道DFS+剪枝,轻轻松松

#include<bits/stdc++.h>
using namespace std;
int c[15][15],a[15],b[15]= {0};
int n,m,flag=0;
void dfs(int k,int sum);
int main()
{
	scanf("%d%d",&n,&m);
	c[1][1]=1;
	for (int i=2; i<=n; i++) { //杨辉三角
		c[i][1]=c[i][i]=1;
		for (int j=2; j<n; j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; 
	}
	dfs(1,0);
	return 0;
}
void dfs(int k,int sum)
{
	if (sum>m) 
	return; //剪枝
	if (k>n) {
		if (sum==m) {
			flag=1;
			for (int i=1; i<=n; i++) 
			cout<<a[i]<<" ";
			exit(0);
		}
		return;
	}
	for (int i=1; i<=n; i++) { //全排列
		if (b[i]) continue;
		b[i]=1;
		a[k]=i;
		dfs(k+1,sum+c[n][k]*i); //*该数
		b[i]=0;
	}
}

这里运用了杨辉三角,有兴趣的可以自己算一下,找找规律

国庆节快乐!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值