SSL-ZYC 洛谷 P1118 数字三角形
题目大意:
有这么一个游戏:
写出一个1~N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置。下面是一个例子:
3 1 2 4
4 3 6
7 9
16
最后得到16这样一个数字。
现在想要倒着玩这样一个游戏,如果知道N,知道最后得到的数字的大小sum,请你求出最初序列a[i],为1~N的一个排列。若答案有多种可能,则输出字典序最小的那一个。
思路:
注:这道题不是那道简单的DP数字金字塔!
虽然这道题还是很简单。。。
我们观察一下,就可以发现:
n=2,最终得a+b
n=3,得a+2b+c
n=4,得a+3b+3c+d
n=5,得a+4b+6c+4d+e
每个字母的系数为杨辉三角第行的数!
、
那么这道题的方法就很明确了:
1.由于n<=13,所以可以暴力求杨辉三角。
2.DFS,搜索。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
int n,ok,m,a[101][101],o[101],t[101];
void dfs(int x,int k) //DFS搜索
{
if (x>n)
{
if (k==m) //和正好为m
{
for (int i=1;i<=n;i++) printf("%d ",o[i]);
ok=1;
}
return;
}
if (k>m) return; //剪枝
for (int i=1;i<=n;i++)
{
if (t[i]==0) //没有用过这个数
{
t[i]=1;
o[x]=i;
dfs(x+1,k+i*a[n][x]);
t[i]=0;
o[x]=0;
}
if (ok==1) return;
}
}
int main()
{
scanf("%d%d",&n,&m);
a[0][1]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=i;j++)
a[i][j]=a[i-1][j]+a[i-1][j-1]; //求杨辉三角
dfs(1,0);
return 0;
}