【UVA679】Dropping Balls 解题报告
程序员文章站
2024-03-18 21:50:10
...
题目链接:点击打开链接
是一个二叉树的编号,首先想到要最后一个球,那我就模拟从第一个球开始,走过的改变状态:要么从关闭(0)变为开启(1),要么从开启(1)变为关闭(0)。用一个数组保存结点状态。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxd = 20;
int s[1<<maxd];
int main(){
int l;
while(scanf("%d",&l)){
if(l == -1)
break;
while(l--){
memset(s,0,sizeof(s));
int D,I;
scanf("%d %d",&D,&I);
int n = (1<<D)-1; //最大结点
int k = 1; //每次的结点
for(int i = 0;i < I;i++)//
{
k = 1;
while(1)
{
s[k] = !s[k]; //经过的点改变,不然先变k,就相当于改下一点的状态
if(s[k])
k = 2*k;
else
k = 2*k+1;
if(k > n)
break;
}
}
printf("%d\n",k/2);
}
}
return 0;
}
然后编写完成,兴高采烈的去Submit,结果显示:Time Limit Exceeded
原来是每次输入,都要把所有点跑一次,而I的可以最大到2^D-1
这样子就一个数据就要高达(2^20)*20,而输入数据最多为1000组。而一般1s的操作4*(10^8)。这样子就TLE了。
分析可以发现,每次到一个节点,奇数点(状态为0)往左边走,偶数点往右边走。
而到下一层同样的道理,所以每次就判断最后一个球的奇偶性即可。
比如上一层的1,3,5,7,9都会往左边走到下一层,而下一层又要从1,2,3,4,5这样子,所以1/2+1, 3/2+1, 5/2+1…,所以奇数往左边走的,就 I = I/2+1。然后再继续判断奇偶性。
而原本上一层是偶数的,2,4,6,8,10会往右边走到下一层,而下一层又要从1,2,3,4,5这样子,所以2/2, 4/2, 6/2…,所以奇数往右边走的,就 I = I/2。然后再继续判断奇偶性。
所以每次的输入,就直接考虑最后一个球I即可。只要走到最后一层D。这样子每次数据处理只用最多20,就不会TLE了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int l;
while(scanf("%d",&l)){
if(l == -1)
break;
while(l--){
int D,I;
scanf("%d %d",&D,&I);
//**改进代码**//
//由于每个球,先进左子树,下一个就进右子树,按奇偶性判断
for(int i = 0;i < D-1;i++)
{
if(I%2)
{
k = k*2;
I = I/2+1;
}
else
{
k = k*2+1;
I /= 2;
}
}
printf("%d\n",k);
}
}
return 0;
}
最后去提交,发现AC了。万岁!!!!!
上一篇: UVa 712 - S-Trees
下一篇: P1515 旅行