解题思路:
(1)首先读懂题目,将一个十进制数分解成2进制,即2的几次方,表示为2(n),同时,这个n不能超过2,如果超过2了,必须再次分解成2的几次方
(2)然后发现,那不就是对每一个数都要进行分解么,先分解一遍,再扫一遍,如果有幂次方大于2的,再次分解,一层层往下钻,直到小于等于2了,返回即可,想到了DFS
(3)DFS本质上就是递归,回忆DFS的算法框架,首先确定出口,当分解的这个数num小于3的时候,return 即可
(4)再看如何得到这些分解的数呢?就是先将一个数转化为2进制,那么可以利用除2取余,逆序排列的方法,将二进制数存到一个数组中,对应的数组下标就是2的几次,然后再对下标进行判断,如果下标超过了2,并且此位置上是1的话,那么需要对这个下标继续分解。如图:
(5)那么在每次分解的时候,可以维护一个布尔数组vis,用来存放对应的0和1,数组的下标便是对应的2的几次方,将一个数转化为二进制数并存放到vis中后,便可以从下标递减的顺序来判断元素值是否为1,如果是,判断对应的下标是否超过了2,如果没有超过,那么分类判断,如果是0或者2的话,输出2(n),如果是1的话,直接输出2.
(6)然后还涉及到一个打标记的问题,因为要输出+号,那么每次循环判断前bool flag=0,输出首部后,接下来的输出都要在前面加上+号,这样末尾就不会有加号。
#include<bits/stdc++.h>
using namespace std;
int n;
void dfs(int len,int num)
{
if(num<3)//递归出口,如果下标小于3,返回
return ;
bool vis[100]={0};//存放2进制数的数组
while(num!=0)
{
vis[++len]=num%2;//将二进制的余数存到vis数组中
num=num/2;//继续缩小2倍
}
bool flag=0;//标记是否输出+号
for(int i=len;i>=0;i--)//从二进制数的下标从大到小遍历
{
if(vis[i]==1)//如果元素值为1
{
if(i<=2)//如果下标比3小的话
{
if(i!=1)//如果不是1
{
if(flag==0)
{
cout<<"2("<<i<<")";
flag=1;
}
else
cout<<"+2("<<i<<")";
}
else//如果是1的话
{
if(flag==0)
{
cout<<"2";
flag=1;
}
else
cout<<"+2";
}
}
else//如果下标大于2的话
{
if(flag==0)
{
cout<<"2(";//输出首部
dfs(-1,i);//继续 递归分解
flag=1;//打上标记
cout<<")";
}
else
{
cout<<"+2(";
dfs(-1,i);
cout<<")";
}
}
}
}
}
int main()
{
cin>>n;
dfs(-1,n);//-1表示数组的下标,因为要从下标0开始存
return 0;
}