ZOJ-1062-Trees Made to Order

被這到題小鬱悶了一下,終於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;
}
發佈了68 篇原創文章 · 獲贊 26 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章