UVA1354枚舉二叉樹
阿新 • • 發佈:2019-03-04
回溯法 tin 創建 很多 cstring max 結果 scan include
枚舉二叉樹的方式有很多,其中一種方式就是每次從一個集合中挑選兩個點出來,一個做左子樹,一個做右子樹,直到集合中只剩下一個節點位置
那麽問題就在於如何挑選?因為必須創建節點加入集合當中去。
我一開始的思路是使用vecoter,每挑選一個就刪除一個,並把新創建的節點加入到vector中去。
但是這種方式是行不通的,因為當回溯的時候,vector不可能恢復原樣。所以使用的方法只能是在數組的末尾添加,每挑選一個節點,就設置一次vis,當第cur次挑選的時候,挑選的範圍是num_node + cur.這很好理解,第cur次挑選的時候,需要考慮前面cur-1次挑選完後新創建的節點。
本質還是回溯法一共有num_node - 1個步驟,每個步驟的可以選擇的節點數是有限制的
需要註意的是,挑出來的兩個節點放在左面和右面的結果是不一樣的。所以需要考慮到所有的情況(挑選的時候的第二層循環中的j,是從0開始的,而不是從i開始的)
如果左右是一樣的,那麽可以從i開始
下面附上代碼:
//我發現網上寫的是些什麽玩意 //枚舉二叉樹 //每次枚舉兩個節點,並將兩個節點合並成一個節點,然後集合中,供下次選取 //使用vector,和vector中的erase函數 //至於汝佳寫的枚舉子集的方式,先放一放吧,看的不是很懂 #include<cstdio> #include<cstring> #include<algorithm> usingnamespace std; const int maxn = 6; double max_room,room; int num_node; struct node { double w; double left; double right; node(double c = 0,double a = 0,double b = 0):w(c),left(a),right(b){} }Node[1<<maxn];//1<<maxn足夠,因為這是一棵有maxn層的完全樹,而我們要求的樹葉只有maxn層的樹。 int vis[1<<maxn]; void DFS(int cur) { if(cur == num_node -1 ) { double now_room = Node[2 * (num_node - 1)].left + Node[2 * (num_node - 1)].right; if(now_room > max_room && now_room < room) { max_room = now_room; } } else { for(int i = 0;i < num_node + cur;i++)//i挑的是左樹,j挑的是右樹 { for(int j = 0;j < num_node + cur;j++) { if(i == j) continue; if(!vis[i] && !vis[j]) { //都沒有訪問過 vis[i] = vis[j] = 1; Node[num_node + cur].w = Node[i].w + Node[j].w; double left = Node[j].w / Node[num_node + cur].w; double right = Node[i].w /Node[num_node + cur].w; Node[num_node + cur].left = max(left + Node[i].left,Node[j].left - right); Node[num_node + cur].right = max(right + Node[j].right,Node[i].right - left); DFS(cur + 1); vis[i] = vis[j] = 0; } } } } } int main() { #ifdef local freopen("input.txt","r",stdin); #endif int kase; scanf("%d",&kase); for(int i = 0;i < kase;i++) { max_room = 0; memset(vis,0,sizeof(vis)); memset(Node,0,sizeof(Node)); scanf("%lf%d",&room,&num_node); for(int j = 0;j < num_node;j++) { scanf("%lf",&Node[j].w); } DFS(0); if(max_room == 0) printf("-1\n"); else printf("%.12lf\n",max_room); } return 0; }
至於汝佳大神的動態規劃的實現,我暫時還看不太懂,以後再看吧
UVA1354枚舉二叉樹