UVA 839 Not so Mobile 解题报告

题目大意:

        给出每个支点的左右物体重量和到支点的距离,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。
  • 这个题是入门,但紫书上说本题极为重要。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeffrey.pace

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值