对这道题。。。只能说,数学太重要了
第一次作死使用链表二叉树模拟,结果TLE
二叉树模拟(错误一):默默吐槽。。好长,流泪不止
#include<iostream>
#include<string>
#include<queue>
#include<math.h>
using namespace std;
struct Node { //Node节点
int data;
bool is_on;
Node* leftchild, *rightchild;
Node(int Data, bool Is_on,Node* Lchild=nullptr,Node* Rchild=nullptr):data(Data),is_on(Is_on),
leftchild(Lchild), rightchild(Rchild) {
;
}
};
Node* root; //指向根节点
void create_tree(int d) //根据深度建树
{
bool h;
h = false;
root = new Node(1,h);
queue<Node*> my_queue;
my_queue.push(root);
int i = 1;
int hh = 1 << d-1;
while (i<=hh*2) //为每个节点编上对应的编号
{
Node* tmp = my_queue.front();
my_queue.pop();
tmp->leftchild = new Node(++i, h);
tmp->rightchild = new Node(++i, h);
my_queue.push(tmp->leftchild);
my_queue.push(tmp->rightchild);
}
}
int last_ball(int num) //得到最后一个的位置
{
int position = 1;
for (int i = 0; i < num; i++)
{
Node* tmp = root;
while (tmp->rightchild != nullptr)
{
if (tmp->is_on == false)
{
tmp->is_on = true;
tmp = tmp->leftchild;
}
else
{
tmp->is_on = false;
tmp = tmp->rightchild;
}
}
position = tmp->data;
}
return position;
}
void deleteTreeHelp(Node* r)
{
if (r != nullptr)
{
if (r->leftchild != nullptr)
deleteTreeHelp(r->leftchild);
if (r->rightchild != nullptr)
deleteTreeHelp(r->rightchild);
delete r;
}
}
void deleteTree() //每次循环后需要删除树
{
deleteTreeHelp(root);
}
int main(void)
{
int d, num; //d为深度, //num为小球个数
int position; //最终的位置
while (cin >> d >> num && d != -1)
{
create_tree(d); //先根据深度建树
position = last_ball(num); //模拟num个小球下落过程
cout << position << endl;
deleteTree(); //删除树
}
}
然后只能去看紫书,第一种TLE的方法,也是模拟,但因为用的是数组(完全二叉树用数组很方便,为什么之前没想到),代码就不放出来了,最后还是TLE,因为还是很耗时。
只能拿出最终武器,利用数学方法(之前做约瑟夫环的时候也是这样,数学方法特别重要),思路是这样的:
1.因为每个节点的状态要么是开启,要么是关闭,所以可以用取模运算进行判断
2.其中比较精华的是,用I=(I+1)/2 OR I /= 2 来判断小球是第几个落在该节点,这一点非常棒,而且只需要对最后一个小球进行模拟
代码如下:
#include<cstring>
#include<cstdio>
const int maxd = 20;
int s[1 << maxd];
int main(void)
{
int D, I;
int count;
scanf("%d", &count);
while (scanf("%d%d", &D, &I) == 2)
{
int k = 1;
for (int i = 0; i < D - 1; i++)
{
if (I % 2) {
k = k * 2; I = (I + 1) / 2; //奇偶性。。
}
else {
k = k * 2 + 1; I /= 2;
}
}
printf("%d\n", k);
}
}