算法分析:典型的DP!
1 ->?
1 ->2=min(1*2,1*3,1*5,1*7)
1 ->2 ->3=min(2*2,1*3,1*5,1*7)
1 ->2 ->3 -> 4 = min(2*2,2*3,1*5,1*7)
1 ->2 ->3 -> 4 ->5= min(3*2,2*3,1*5,1*7)
状态转移方程
F(n)=min(F(i)*2,F(j)*3,F(k)*5,F(m)*7)(n>i,j,k,m) 特别的: i,j,k,m 只有在本项被选中后才移动。对应的i,j,k,m要++ 。
PS:一次移动可能不止一项,若四项中有几项相同时,它们也得移动。这点一直没考虑清楚,浪费了很长时间。
AC代码:
#include<stdio.h>
inline int min(int a, int b)
{
return (a)<(b)?(a):(b);
}
int f[5845];
int main(){
int n,i,j,d,k,m;
f[0]=1;
f[1]=1;
n=25;
d=j=1;
k=m=1;
for(i=2;i<=5842;i++){
int temp=min(min(f[d]*2,f[j]*3),min(f[k]*5,f[m]*7));
f[i] = temp;
if(temp == f[d]*2){
d++;
}
if(temp==f[j]*3){
j++;
}
if(temp==f[k]*5) {
k++;
}
if(temp==f[m]*7) {
m++;
}
}
while(scanf("%d",&n)!=EOF&&n!=0){
if(n%10==1 && n%100 != 11){//个位数是1,但十位数不是1
printf("The %dst humble number is %d.\n",n,f[n]);
} else if(n%10==2 && n%100 != 12){//个位数是2,但十位数不是1
printf("The %dnd humble number is %d.\n",n,f[n]);
} else if(n%10==3 && n%100 != 13){//个位数是3,但十位数不是1
printf("The %drd humble number is %d.\n",n,f[n]);
} else
printf("The %dth humble number is %d.\n",n,f[n]);
}
return 0;
}