算法分析:典型的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; }