{这个题5个正确,五个超时,不要盲目相信个人代码,谁有更好的算法或者优化请留言,(*^__^*) 嘻嘻……}算法
贪玩的sunnypig请Charles为他打造一个奇幻世界,Charles欣然答应了。然而一贯善于出难题的Charles是决不会轻易让sunnypig轻松拥有一个奇幻世界的,因而Charles在建造过程当中设置了重重机关,只有在sunnypig破解了这些障碍以后,才能尝试到奇幻世界中最有玩头的终极宝贝——时空穿梭机。虽然奇幻世界中其余的宝贝也颇有趣,但贪玩的sunnypig怎能放过打boss的机会呢?因而他开始了破解障碍的旅程。测试
第二道障碍来源于一种古老的数学发现——杨辉三角,不过应该是倒过来的杨辉三角。若给出1~n的一个排列A,则将A一、A2相加,A二、A3相加……An-一、An相加,则获得一组n-1个元素的数列B;再将B一、B2相加,B二、B3相加,Bn-二、Bn-1相加,则获得一组n-2个元素的数列……如此往复,最终会得出一个数T。而Charles给sunnypig出的难题即是,给出n和T,再尽量短的时间内,找到能经过上述操做获得T且字典序最小的1~n的排列。通过汉诺塔问题的训练,sunnypig开始沉着的思考。。。优化
本题有多组数据,对于每组数据:
一行两个整数n(0<n<=20),t即最后求出来的数。ui
用文件结尾符判断输入结束。spa
对于每组测试数据输出一行n个整数,用空格分开,行尾无多余空格,表示求出来的知足要求的1~n的一个排列。code
由题意得,有两个数a,b时,t=a+b;blog
有三个数a,b,c 时 t=a+2b+c排序
有四个数a,b,c,d时 t=a+3b+3c+d数学
……it
不可贵出,符合杨辉三角
因而,能够枚举每一个系数后的值,而后进行相加,作适当的剪枝,能够得出答案
有人说是用排序不等式作,惋惜本人是一枚学渣兼蒟蒻,即便看到那个所谓a^2+b^2+c^2>=ab+ac+bc也不知道该怎么用......
1 program yanghui; 2 var n,i,j,sum,t,flag:longint; 3 a:array[0..20,0..20] of longint; 4 b:array[0..20] of longint; 5 s:array[0..20] of longint; 6 pd:Array[1..20] of boolean; 7 procedure yanghui;//求出杨辉三角 8 var i,j:longint; 9 begin 10 a[1,1]:=1; 11 for i:=2 to 20 do 12 begin 13 for j:=1 to i do 14 begin 15 a[i,j]:=a[i-1,j]+a[i-1,j-1]; 16 end; 17 end; 18 end; 19 procedure dfs(n,k:longint); 20 var i:Longint; 21 begin 22 if flag=1 then exit;//如已经有答案,退出 23 if sum>t then exit;//如已经超过所求值,退出 24 if sum+(s[n]-s[k-1])*n<t then exit;//如不可能达到所求值,退出 25 if (k-1>(n+1) div 2) and(b[n-k+2]>b[k-1]) then exit;//如后面的值比对应位置的值大,退出(由于此时不是字典序最前的值) 26 if k=n+1 then 27 begin 28 if sum=t then 29 begin 30 for i:=1 to n do write(b[i],' '); 31 writeln; 32 flag:=1; 33 end; 34 exit; 35 end; 36 for i:=1 to n do//简单回溯寻找答案 37 if (not pd[i]) then 38 begin 39 sum:=sum+i*a[n,k]; 40 b[k]:=i; 41 pd[i]:=true; 42 dfs(n,k+1); 43 if flag=1 then exit; 44 sum:=sum-i*a[n,k]; 45 pd[i]:=false; 46 end; 47 end; 48 49 begin 50 yanghui; 51 while not eof do 52 begin 53 fillchar(pd,sizeof(pd),false); 54 flag:=0; 55 sum:=0; 56 read(n,t); 57 for i:=1 to n do s[i]:=s[i-1]+a[n,i];//前缀和,表示第n行前i个杨辉三角上的数值之和 58 dfs(n,1); 59 end; 60 end.