枚举二叉树的方式有很多,其中一种方式就是每次从一个集合中挑选两个点出来,一个做左子树,一个做右子树,直到集合中只剩下一个节点位置
那么问题就在于如何挑选?因为必须创建节点加入集合当中去。
我一开始的思路是使用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> using namespace 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; }
至于汝佳大神的动态规划的实现,我暂时还看不太懂,以后再看吧
原文地址:https://www.cnblogs.com/TorettoRui/p/10471541.html
时间: 2024-10-10 07:39:51