题目大意:
给出每个支点的左右物体重量和到支点的距离,wl,dl,wr,dr
分别表示左边物体重量和到左边的距离,右边物体重量和到右边的距离,当wl*dl==wr*dr
成立时,说明杠杆平衡。忽略所有绳子和杠杆重量。
注意事项:
- 只有所有天平都平衡,输出YES;
- 该题的数据为递归输入
#include <iostream> // Uva 839
using namespace std;
typedef struct Tree
{
int data[4];
struct Tree* LChild=NULL;
struct Tree* RChild=NULL;
}TREE,*LPTREE;
LPTREE CreateNode(int W1, int D1, int W2, int D2)
{
LPTREE node = (LPTREE)malloc(sizeof(TREE));
node->data[0] = W1;
node->data[1] = D1;
node->data[2] = W2;
node->data[3] = D2;
return node;
}
void BuildTree(LPTREE& node) //建树
{
int W1, D1, W2, D2;
cin >> W1 >> D1 >> W2 >> D2;
node = CreateNode(W1, D1, W2, D2);
if (W1 == 0)
BuildTree(node->LChild);
if (W2 == 0)
BuildTree(node->RChild);
if (W1 != 0 && W2 != 0) // 若该节点没有子天平, 给它的左右节点NULL
{
node->LChild = NULL;
node->RChild = NULL;
}
}
int DFS(LPTREE root) // 后序遍历并判断是否平衡
{
if (root == NULL)
return -1; // 空树
if (root->LChild != NULL)
root->data[0] = DFS(root->LChild); // 左子树
if (root->RChild != NULL)
root->data[2] = DFS(root->RChild); // 右子树
if (root->data[0] == -1 || root->data[2] == -1)
return -1; // 非法,剪枝
//判断天平是否平,若平衡,返回重量和,不平衡,返回-1
if (root->data[0] * root->data[1] == root->data[2] * root->data[3])
return root->data[0] + root->data[2]; // 平衡,返回左右重量和
else
return -1; // 不平衡,标记-1
}
void Remove_Tree(LPTREE root) // 避免内存泄露
{
if (root == NULL)
return;
Remove_Tree(root->LChild);
Remove_Tree(root->RChild);
delete root;
}
int main()
{
int kase;
cin >> kase;
while (kase--)
{
LPTREE TreeRoot;
BuildTree(TreeRoot); // 建树
DFS(TreeRoot)!=-1 ? cout << "YES\n" : cout << "NO\n";
if (kase)
cout << endl;
Remove_Tree(TreeRoot); // 销毁树
}
}
心得:
- 刚开始入门二叉树这个数据结构,就发现了递归的强大,树的建立、遍历、销毁都可以运用它,以后要多加练习。
- 在写建树的函数时,一开始写 void BuildTree(LPTREE node) ,但会报错。后来传参时使用了传引用,解决了问题。不过我还是不太清楚为什么需要引用o_O。
- 这个题是入门,但紫书上说本题极为重要。