您的位置:首页 > 其它

ZOJ-1062-Trees Made to Order

2007-08-05 06:24 288 查看
被这到题小郁闷了一下,终于AC了,郁闷人的要点说到底是数数的问题,从哪数,数到哪,算几?

AC率高的有两种,一种是真的太简单,sample数据覆盖广,另一种是这道题,好不容易AC了,赶紧再多来几遍看看能不能少用些时间或memory。1062高达63%的AC率,但却是道稍有难度的题,主要是中间算每段的起始和子树的节点数和入口编号有些琐碎。

题目算法

先说明一下,关于递归函数的参数,我也在网上搜到看了别人的程序,有使用单独一个参数就是编号本身的,这个当然很好,尤其是看起来程序非常清晰,不过就是能得出子树的编号,说明也已经得到它的节点数目m以及它是有m个节点的树中的第几个。。。所以干脆还是传节点数目m和它在m个节点的树中的名次。

废话不说了,算法如下:

1。首先计算出所有含有m个节点的树的总数目,存在idex[m]里,这一步我是先写过程序算出按照题目的要求,节点数不会超过18,并且手动把结果存在程序里了。idex[0]=1。这个程序应该很好些的,就不详细说了。

2。算出输入数字的节点数目及其名次,调用递归函数void gettree(int node, long bit).

3。在递归函数中,从i=0开始,逐次执行temp -= idex[i] * idex[node-1-i];,直到temp<=0,这时恢复temp最后一次大于0的值。

讲到这里,先给个例子,比如题中有图的20,那么20-1-2-5=12,这时再减14就为负所以20有4个节点,除去根节点,还剩3个节点,3个节点分配顺序由小到大为:

0 3---idex[0]*idex[3] = 1*5 = 5
1 2---idex[1]*idex[2] = 1*2 = 2
2 1---idex[2]*idex[1] = 2*1 = 2
3 0---idex[3]*idex[0] = 1*2 = 5

这时12-5=7,7-2=5,5-3=2,2-5<0,所以这3个节点的分配为左3右0。

4。知道了左右子树的节点分配,也就知道了左右子树各能产生多少种可能,利用乘法原理。

这时剩下的数字代表第几位。。。所以减1然后处以右子树的可能组合数idex[node-1-i],又因为除下来的数又是从0开始数,所以再加1,于是就是:

x = ((temp-1)/idex[node-1-i])+1,这是左子树在节点为i个时的入口编号,接下来求得最后剩余的数字,

y = temp-(x-1)*idex[node-1-i];,这是右子树在节点为node-1-i个时的入口编号。

(这里的node指得是当前整个树的节点数目)

5。接下来调整相应的输出格式,递归,结束条件是node==1,输出X。

程序清单如下

//C++ 00:00.00 432K
#include<stdio.h>

long idex[19];
long in;

void gettree(int node, long bit)
{
if(1==node)
{
printf("X");
}
else
{
long temp=bit;
int i;
for(i=0;i<node;i++)
{
temp -= idex[i] * idex[node-1-i];
if(temp<=0)
break;
}
temp += idex[i] * idex[node-1-i];
long x,y;
x = ((temp-1)/idex[node-1-i])+1;
y = temp-(x-1)*idex[node-1-i];
if((node-1-i>0)&&(i>0))
{
printf("(");
gettree(i,x);
printf(")X(");
gettree(node-1-i,y);
printf(")");
}
else if(i>0)
{
printf("(");
gettree(i,x);
printf(")X");
}
else
{
printf("X(");
gettree(node-1-i,y);
printf(")");
}
}
}

void solve()
{
long temp=in;
int i;
for(i=1;;i++)
{
temp -= idex[i];
if(temp<=0)
break;
}
temp += idex[i];
gettree(i,temp);
printf("/n");
}

int main()
{
// freopen("1062.txt","r",stdin);
idex[0] = 1;
idex[1] = 1;
idex[2] = 2;
idex[3] = 5;
idex[4] = 14;
idex[5] = 42;
idex[6] = 132;
idex[7] = 429;
idex[8] = 1430;
idex[9] = 4862;
idex[10] = 16796;
idex[11] = 58786;
idex[12] = 208012;
idex[13] = 742900;
idex[14] = 2674440;
idex[15] = 9694845;
idex[16] = 35357670;
idex[17] = 129644790;
idex[18] = 477638700;
while(scanf("%ld", &in)!=EOF && in>0)
solve();
// fclose(stdin);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: