d[n]=min(dp[n-1]+1,dp[n/2]); n为偶数
dp[n]=dp[n-1]+1; n为奇数
其实dp[n-1]和dp[n/2]哪个小呢?
我们用二进制表示一个数 因为此时n为偶数所以,尾为0,我们希望通过减去一能否可以xxxxx数出现更多的0;
1.右移动一位:减少一位,末尾的0去掉
2.减一:xxx0-1,若是xx10的形式,结果为xx01,通过减一,我们没占什么便宜,0,1总数没变。
xxx00减去一,出现xx11,天啊,增加更多的1,算了吧,通过此处我们发现,通过减去一,我们没办法得到更多的0;
所以此题就很简单了,遇到一就减去一,遇到0就右一位,所以总次数就是count(1)X2+count(0)
count(1)就是二进制中1的个数。
#include<iostream> using namespace std; int main() { cout<<"输入你要求的数"<<endl; int m; cin>>m; int sum=0; while(m!=1) { if(m&1) sum+=2; //得到最后一位是1,是0 else sum+=1; m=m>>1; } cout<<sum<<endl; system("pause"); return 0; }
不用分析,直接动态规划,畅快,但效率。。。
#include<iostream> using namespace std; int d[2014]; int min(int x,int y) { if(x>y) return y; else return x; } int main() { int n; cin>>n; memset(d,0,sizeof(d)); d[1]=0; d[2]=1; for(int i=3;i<=n;i++) { if(i%2==0) { d[i]=min(d[i/2],d[i-1])+1; } else d[i]=d[i-1]+1; cout<<d[i]<<endl; } system("pause"); return 0; }
如果改成n为偶数则除以2,为奇数则-1或加1,那最小次数呢,如果是f(7)=4,就是说7到1至少要4次。
偶数的时候,直接右移位,不考虑。
奇数的时候,是加1还是减去1呢?
奇数可以表示为 xxxx1的形式。
1.减去1很简单,xxxx0的形式,
2 xxxx1呢,(a)如果xxx11加上一 就是 xxx00可能比这个还多的0,如果xxx11中11前面还有1的话,总是很爽, (b)如果xxx01呢,加上1就是xxxx10,0的个数没变,
2中(a)是最好的,那2中(b)和 1 谁好呢? xxxx01加上1,xxx10,xxxx01减去一,变成xxx00,显然1好。
综上所述:
.m&1==0 m=m>>1
否则
m&10判断倒数第二位是1,是0?
为1:则 m=m+1’';
为0,则 m=m-1;
#include<iostream> using namespace std; int main() { cout<<"输入你要求的数"<<endl; int m; cin>>m; int sum=0; while(m!=1) { if(m&1) { sum++; if(m&2) { m=m+1; } else { m=m-1; } } //得到最后一位是1,是0 else {sum+=1; m=m>>1; } } cout<<sum<<endl; system("pause"); return 0; }