小球下落,紫书P148UVa679
来源:互联网 发布:linux vim 编辑:程序博客网 时间:2024/04/30 14:34
这是一道我非常喜欢的算法题目。本题的技巧性非常高。虽然是一道依据于满二叉树题目,但是单纯的模拟题目小球下落的程序,也许能过几个小范围测试数据,数据量太大的时候必定TL。即使是模拟程序,刘也依然写的非常精简。其中k = s[k] ? k*2 : k*2+1;这个语句很值得c++不熟练的选手学习。
#include <cstdio>#include <cstring> const int maxd 20;int s[1<<maxd];int main(){ int D,I; while (scanf("%d%d", &D, &I) == 2){ memset(s, 0, sizeof(s)); int k, n = (1<<D)-1; for (int i = 0; i < I; i++){ k = 1; for(;;){ s[k] = !s[k]; k = s[k] ? k*2 : k*2+1; if (k>n) break; } } printf("%d\n", k/2); } return 0;}
由上面程序可知,当数据量很大的时候,是一定会超时的。那么真正高效率的算法是什么?
对于每一棵树而言,落到其根节点的第奇数个小球都落入其左子树,第偶数个小球都落入其右子树。而落入其左子树的小球n,是第(n+1)/2个落入其左子树的。落入右侧的同理。对于他的子树也按照此规律类推,即可根据最后一个小球的编号直接递推出其最终落在根节点的位置,省去了普通算法中前n-1次的复杂运算,大大降低了时间复杂度。
// UVa679 Dropping Balls// Rujia Liu#include<cstdio>int main() { int T, D, I; scanf("%d", &T); while(T--) { scanf("%d%d", &D, &I); 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); } return 0;}
哈哈,正解算法程序算上注释才刚刚16行。实在是非常有趣。
阅读全文
0 0
- 小球下落,紫书P148UVa679
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- 小球下落
- [算法]小球自由下落
- 小球下落问题
- cookei和session
- hdu 1827 Summer Holiday【Tarjan缩点】
- 类的默认成员函数
- if __name__=="__main__":
- C#中静态与非静态方法比较
- 小球下落,紫书P148UVa679
- 云中歌一键端+GM工具+架设教程
- 基于CENTOS7.0+ mariadb 安装ownCloud
- 常用知识——linux内核中常见的内存分配方法
- Oracle存储过程及函数的练习题
- Python:把关系型数据库的查询结果转成dataframe
- bzoj 1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区(暴力)
- 38. Count and Say
- 非常详细的 Docker 学习笔记