我的思路:可以将天平看做一棵二叉树,二叉树的每个节点要记录其父节点。然后其实就是一个建树的过程,遇到 0 节点就向下延伸,每当一个节点的左右子树确定(其重量也随之确定),就计算其是否平衡,然后一直向上追溯,直到该节点尚未平衡,继续建树,直至整棵树建好,是否平衡也随之确定。
version 1(40ms):
#includeusing namespace std;const int maxn = 10000 + 5;int t,wl,dl,wr,dr;struct node{ int w = 0,d = 0; struct node* dad = NULL; struct node* left = NULL; struct node* right = NULL;};node* newnode(){ return new node; }void build_tree(int& mark){ node* root = newnode(); node* t = root; while(!root->w){ scanf("%d%d%d%d",&wl,&dl,&wr,&dr); if(!t->left){ t->left = newnode(); t->left->w = wl; t->left->d = dl; t->left->dad = t; } if(!t->right){ t->right = newnode(); t->right->w = wr; t->right->d = dr; t->right->dad = t; } if(t->left->w && t->right->w){ while(t->left->w && t->right->w){ t->w = t->left->w + t->right->w; if(mark && t->left->w*t->left->d != t->right->w*t->right->d) mark = 0; if(t == root) break; t = t->dad; } t = (!t->left->w ? t->left : t->right); } else if(!t->left->w) t = t->left; else t = t->right; }}int main(){ // freopen("data.in","r",stdin); // freopen("data.out","w",stdout); scanf("%d",&t); while(t--){ int mark = 1; build_tree(mark); printf("%s\n",mark ? "YES" : "NO"); if(t) putchar('\n'); } return 0;}
看了看书上的代码,直接递归就行。。。既简洁又优美。智商的差距。。。
version 2(20ms):
#includeusing namespace std;const int maxn = 10000 + 5;int t,w;bool solve(int& w){ int wl,dl,wr,dr; scanf("%d%d%d%d",&wl,&dl,&wr,&dr); int bl = 1,br = 1; if(!wl) bl = solve(wl); if(!wr) br = solve(wr); w = wl + wr; return bl && br && wl*dl == wr*dr;}int main(){ // freopen("data.in","r",stdin); // freopen("data.out","w",stdout); scanf("%d",&t); while(t--){ printf("%s\n",solve(w) ? "YES" : "NO"); if(t) putchar('\n'); } return 0;}