一、由整数1,2,3.....组成了一颗无限大的满二叉树,给出2个正整数,代表二叉树中的节点,求出这2个节点最近的公共祖先
int common(int x , int y){ if(x = y) return x; else if(x > y) return common(x/2,y); else return common(x,y/2); }二、求逆波兰表达式
逆波兰表达式是一种把运算符前置的算术表达式,例如(2 + 3) *4的逆波兰表示法为*+234。
double exp(){ char a[10]; scanf("%s",a); switch(a[0]){ case '+' : return exp() + exp(); case '-' : return exp() - exp(); case '*' : return exp() * exp(); case '/' : return exp() / exp(); default:return atof(a); } }
将逆波兰表达式转换成常规表达式输出,可以包含多余的括号
void exp(){ char a[10]; scanf("%s",a); switch(a[0]){ case '+' : cout << "(" ; exp(); cout << "+" ; exp(); cout << ")"; break; case '-' : cout << "(" ; exp(); cout << "-" ; exp(); cout << ")"; break; case '*' : exp(); cout << "*" ; exp(); break; case '/' : exp(); cout << "/" ; exp(); break; default : cout << atof(a) ; } }
三、放苹果
把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问有多少种不同的分法?ps:5,1,1和1,5,1是同一种分法。
int f(int m,int n){ if(m == 0 || n == 1) return 1; if(m < n) return f(m,m); return f(m - n,n) + f(m,n - 1); }
可以用记忆化搜索,把f(m,n)换成f[m][n];
这种做法可以统计总的放法,但是要得到每一种放法,还是要搜索+剪枝
搜索就不说了,主要是剪枝提高了效率,当剩下的苹果平均放到剩余的盘子中的时候,每个盘子分的的苹果数目小于前一个盘子放置的苹果数目,这样就不满足我们给的要求ai-1<ai,所以加上条件
((m - w)/(n - k)) >= s[k - 1]
void dfs(int k, int w){ //初始k=1,w=0;k表示现在已经用的盘子,w表示已经放了几个苹果 if(k == n){ //当最后一个盘子被放置苹果的时候我们进行判断 if(m - w >= s[k - 1]){ s[k] = m - w; int i; for(i = 1;i < n;i++) cout << s[i] << " "; cout << s[i] << endl; } return; } for(int i = 0;i <= m;i++){ if(i >= s[k - 1] && ((m - w)/(n - k)) >= s[k - 1] ){ //如果当前放置的苹果个数大于前一个盘子继续放置,后半部分是剪枝 s[k] = i; w = w + i; k = k + 1; dfs(k,w); w = w - i; k = k - 1; } } }