Uva679

暴力法

典型的二叉树,但是我这里用的是数组,其实是一样的,就初始化数组,然后不断暴力用小球去循环就可以了。
重要结论:父节点是n,那么左子节点是2n,右子节点是2n+1;

代码

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector<bool> v;
int main(void) {
	int D, I;
	cin >> D >> I;
	for (int i = 0; i <= pow(2, D) - 1; i++) {//初始化数组
		v.push_back(false);
	}
	int t = 0;//t来存放最后的小球所在的位置
	for (int i = 0; i < I; i++) {//i个小球循环
		int j = 1;
		for (; j <= pow(2, D - 1) - 1;)//每一个小球循环
		{
			if (v[j])
			{
				v[j] = !v[j];
				j = 2 * j + 1;
			}
			else
			{
				v[j] = !v[j];
				j = 2 * j;
			}
		}
		if (i == I - 1)
			t = j;
	}
	cout << t;
	system("pause");
}

规律法

其实我们只要做一次循环就行,那就是最后一个小球的循环

规律:如果一个小球相对于某一个节点是第奇数个球的话,那就往该节点的左子节点走,否则往右子节点走,这个很简单,那么是不是说我们每走一步就判断最后一个球是现在所处节点的第几个球那么不就知道要往那边走了,那不是节省了很多时间吗?

判断:接下来的关键就是如何去计算相对节点数,假设最后一个小球相对于某一节点是第I个节点,那么如果是奇数,往左走,那么该小球相对于左子节点来说其实就是第I/2+1个球,反之,就是第I/2个球,那么就下就好办了,只要循环走最后一个小球的路就行啦

代码

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector<bool> v;
int main(void) {
	int D, I;
	cin >> D >> I;
	int t = 1;
	for (int i = 1; i < D; i++) {
		if (I % 2) {
			I = I / 2 + 1;
			t = 2 * t;
		}
		else
		{
			I = I / 2;
			t = 2 * t + 1;
		}
	}
	cout << t;
	system("pause");
}

你可能感兴趣的:(算法)