[HDOJ5573]Binary Tree(找规律,贪心)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5573
这个题……规律暂时还找不到,先贡献两发TLE的代码吧,一个dfs一个状压枚举。
- #include <algorithm>
- #include <iostream>
- #include <iomanip>
- #include <cstring>
- #include <climits>
- #include <complex>
- #include <fstream>
- #include <cassert>
- #include <cstdio>
- #include <bitset>
- #include <vector>
- #include <deque>
- #include <queue>
- #include <stack>
- #include <ctime>
- #include <set>
- #include <map>
- #include <cmath>
- using namespace std;
- typedef long long ll;
- const int maxn = ;
- ll n, k;
- ll path[maxn][];
- int pcnt;
- //1 + 0 -
- bool exflag;
- void dfs(ll cur, ll lv, ll id) {
- if(exflag) return;
- if(cur == n && lv == k) {
- for(ll i = ; i < pcnt; i++) {
- printf("%I64d %c\n", path[i][], path[i][] == ? '+' : '-');
- }
- exflag = ;
- return;
- }
- if(cur != n && lv == k) return;
- path[pcnt][] = id;
- path[pcnt++][] = ;
- dfs(cur+id ,lv+, id*);
- pcnt--;
- path[pcnt][] = id;
- path[pcnt++][] = ;
- dfs(cur+id ,lv+, id*+);
- pcnt--;
- path[pcnt][] = id;
- path[pcnt++][] = ;
- dfs(cur-id ,lv+, id*);
- pcnt--;
- path[pcnt][] = id;
- path[pcnt++][] = ;
- dfs(cur-id ,lv+, id*+);
- pcnt--;
- }
- int main() {
- // freopen("in", "r", stdin);
- int T, _ = ;
- scanf("%d", &T);
- while(T--) {
- scanf("%I64d %I64d", &n, &k);
- pcnt = ; exflag = ;
- printf("Case #%d:\n", _++);
- dfs(, , );
- }
- return ;
- }
DFS
- #include <algorithm>
- #include <iostream>
- #include <iomanip>
- #include <cstring>
- #include <climits>
- #include <complex>
- #include <fstream>
- #include <cassert>
- #include <cstdio>
- #include <bitset>
- #include <vector>
- #include <deque>
- #include <queue>
- #include <stack>
- #include <ctime>
- #include <set>
- #include <map>
- #include <cmath>
- using namespace std;
- typedef long long ll;
- const int maxn = ;
- ll n, k;
- ll f[maxn];
- ll ans[maxn];
- bool sub[maxn];
- void init() {
- f[] = ;
- for(int i = ; i < maxn; i++) {
- f[i] = f[i-] * ;
- }
- }
- int main() {
- // freopen("in", "r", stdin);
- int T, _ = ;
- init();
- scanf("%d", &T);
- while(T--) {
- scanf("%I64d %I64d", &n, &k);
- for(int i = ; i <= k; i++)
- ans[i] = f[i-];
- if(n % == ) ans[k]++;
- ll nn = << k;
- bool exflag = ;
- for(ll i = ; i < nn; i++) {
- if(exflag) break;
- ll cur = ;
- memset(sub, , sizeof(sub));
- for(ll j = ; j <= k; j++) {
- if(( << j) & i) {
- sub[j] = ;
- cur -= ans[j];
- }
- else cur += ans[j];
- }
- if(cur == n) exflag = ;
- }
- printf("Case #%d:\n", _++);
- for(ll i = ; i <= k; i++) {
- printf("%I64d ", ans[i]);
- if(sub[i]) printf("-\n");
- else printf("+\n");
- }
- }
- return ;
- }
ENUM
这个题想了很多天,想明白了其实还蛮简单的。
题目给了一棵满二叉树,按照层次遍历从左到右挨个编号1 2 3....问蛤蛤从根节点向下走,走到一个点可以加上当前节点编号也可以删掉当前节点编号。问走k层能否恰好续够n。
题目中给了一个条件:N≤2^K≤2^60
因为读题坑掉了没看到这个条件,浪费了很多时间在例如n=10 k=3的情况上。这种情况在我的搜索中是完全有结果的,但是实际上这个情况不会在题目中出现,因为8<10。
这样就好办了,我们考虑任何一个十进制数都可以表示为二进制,这个二进制表示了某一位上是否要加上对应的2的幂次。
(以上皆为口胡+脑补,正常题解在下面)
N<=2^k意味着我们总能找到第k+1个节点,使得N小于k+1节点的数值。既然如此,我们贪心地选取最左边的一条链。这样,最左边那个点必然是整层最小的。对于本题目而言,总有2^(k+1)-1≥n。
由于最左侧的链均为2的幂次,我们以前的知识中一定有这样一条规律:2^(k)-1=∑i(1,k-1)2^i。表达不清楚,举个例子:32-1=1+2+4+8+16。
我们假设整条长度为k链都是加的,那它的总和就是2^(k+1)-1,我们现在知道要求的n,那我们不需要的那部分的值为2^(k+1)-1-n。
假设这个值为x,那x也总是能表达为一个二进制数,我们只需要在这个链子上找到可以表示x的二进制数的位置,把它们标记为'-'即可。
- #include <algorithm>
- #include <iostream>
- #include <iomanip>
- #include <cstring>
- #include <climits>
- #include <complex>
- #include <fstream>
- #include <cassert>
- #include <cstdio>
- #include <bitset>
- #include <vector>
- #include <deque>
- #include <queue>
- #include <stack>
- #include <ctime>
- #include <set>
- #include <map>
- #include <cmath>
- using namespace std;
- typedef long long ll;
- const int maxn = ;
- ll n, k;
- ll f[maxn];
- ll ans[maxn];
- bool sub[maxn];
- void init() {
- f[] = ;
- for(int i = ; i < maxn; i++) {
- f[i] = f[i-] * ;
- }
- }
- int main() {
- // freopen("in", "r", stdin);
- int T, _ = ;
- init();
- scanf("%d", &T);
- while(T--) {
- scanf("%I64d %I64d", &n, &k);
- memset(sub, , sizeof(sub));
- for(int i = ; i <= k; i++)
- ans[i] = f[i-];
- ll remain = f[k] - n - ;
- if(n % == ) {
- ans[k]++;
- remain++;
- }
- remain >>= ;
- int cnt = ;
- while(remain) {
- if(remain % == ) sub[cnt] = ;
- remain >>= ;
- cnt++;
- }
- printf("Case #%d:\n", _++);
- for(int i = ; i <= k; i++) {
- printf("%I64d ", ans[i]);
- sub[i] ? printf("-\n") : printf("+\n");
- }
- }
- return ;
- }
[HDOJ5573]Binary Tree(找规律,贪心)的更多相关文章
- 找规律/贪心 Codeforces Round #310 (Div. 2) A. Case of the Zeros and Ones
题目传送门 /* 找规律/贪心:ans = n - 01匹配的总数,水 */ #include <cstdio> #include <iostream> #include &l ...
- [LeetCode] 366. Find Leaves of Binary Tree 找二叉树的叶节点
Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...
- [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点
Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...
- LeetCode Minimum Depth of Binary Tree 找最小深度(返回最小深度)
题意:找到离根结点最近的叶子结点的那一层(设同一层上的结点与根结点的距离相等),返回它所在的层数. 方法有: 1.递归深度搜索 2.层次搜索 方法一:递归(无优化) /** * Definition ...
- Codeforces Round #265 (Div. 2) C 暴力+ 找规律+ 贪心
C. No to Palindromes! time limit per test 1 second memory limit per test 256 megabytes input standar ...
- hdu - 6277,2018CCPC湖南全国邀请赛B题,找规律,贪心找最优.
题意: 给出N个小时,分配这些小时去写若干份论文,若用1小时写一份论文,该论文会被引用A次,新写一篇论文的话,全面的论文会被新论文引用一次. 找最大的H,H是指存在H遍论文,而且这些论文各被引用大于H ...
- UVALive - 6577 Binary Tree 递推+找规律
题目链接: http://acm.hust.edu.cn/vjudge/problem/48421 Binary Tree Time Limit: 3000MS 问题描述 Binary Tree is ...
- Full Binary Tree(二叉树找规律)
Description In computer science, a binary tree is a tree data structure in which each node has at mo ...
- [LeetCode] Find Mode in Binary Search Tree 找二分搜索数的众数
Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred ...
随机推荐
- android的布局管理器
理论上通过setContentView(view)能够把一个view设置到activity中,但当你有很多个view控件的时候,就需要用android的布局管理器来管理view控件了. android ...
- 2015 WEB前端学习路线图
2015 WEB前端学习路线图,欢迎小伙伴补充 @落雨
- WinHex分析PE格式(1)
最近在一直努力学习破解,但是发现我的基础太差了,就想学习一下PE结构.可是PE结构里的结构关系太复杂,看这老罗的WiN32汇编最后一章 翻两页又合上了..把自己的信心都搞没了.感觉自己的理解能力不行, ...
- 说说php取余运算(%)的那点事
http://www.phpddt.com/php/php-take-over.html fmod()与 % 区别 都是取余 fmod是函数 原型float fmod(float x, ...
- poj 1185
上一题的升级版 dp[i][j][k] 表示第 i 行状态为 k 第i-1行状态为 j #include <cstdio> #include <cstdlib> #includ ...
- Python - 装饰器使用过程中的误区
曾灵敏 - APRIL 27, 2015 装饰器基本概念 大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, C ...
- codeforces 455B A Lot of Games(博弈,字典树)
题目 参考自博客:http://blog.csdn.net/keshuai19940722/article/details/38455269 //字典树,博弈 根据当前节点的后续来确定当前节点的状态, ...
- C++ 第一次上机作业
今天完成了C++第一次上机作业,感觉比较简单. 题目: 求2个数或3个正整数中的最大数,用带有默认参数的函数实现. 对3个变量按由小到大顺序排序,要求使用变量的引用. 编写一个程序,用同一个函数名对几 ...
- java基础知识回顾之javaIO类---BufferedReader和BufferedWriter
使用了装饰设计模式:此类的设计是为了提高流操作数据的效率.思想就是定义容器将数据进行临时存储,对于缓冲区对象,其实就是将这个容器进行了分装,并提供了更高效的操作方法. BufferReader: pa ...
- Eclipse环境下配置spket中ExtJS提示
使用eclipse编写extjs时,一定会用到spket这个插件,spket可以单独当作ide使用,也可以当作eclipse插件使用,我这里是当作eclipse的插件使用的,下面来一步步图解说明如何配 ...