今天解了HDOJ上的1058题:http://acm.hdu.edu.cn/showproblem.php?pid=1058
这是一道关于动态规划(dynamic programming)的题目,适用DP的算法解决的问题一般都有3个特性:最优化原理、无后向性、子问题重叠性质。
最优化:如果问题的最优解所包含的子问题的解也是最优,那么父问题的解也是最优的,该问题具有最优子结构。
无后向性:若某个阶段的状态确定之后,那么就不会受这个状态后面的决策所影响,也就是说某状态以后的过程不会影响以前的状态,而只与当前的状态有关。
有重叠子问题:指子问题间不是相互独立的,一个子问题的解可能在下一个问题中被多次使用,这是动态规划区别于其它算法的一大特征,也是其一大优势,让问题变得不再那么冗杂。在本题中,每次的map[i]都是用前面得出的map[]值乘以4个因子中的某个得到的。
具体看看这道题,这道题的大体意思就是要你找出以2,3,5,7为因子的数(我们姑且称它们为因子数),按升序排列,然后输入一个n(1<=n<=5842),表示要求输出第n个因子数。具体的输出格式看输出样例,这里输出格式违背了英语的构词原则(估计是出这道题的人不太细心- -),第111个为111th,而121为121st......
代码如下:
1 #include<stdio.h>
2 #include<iostream>
3 using namespace std;
4
5 int map[6000];//开辟一个足够大的数组
6 int min( int a,int b,int c,int d)
7 {//取a,b,c,d中的最小值
8 return (a<b?a:b)<(c<d?c:d)?( a<b?a:b):(c<d?c:d);
9 }
10 void humble( )
11 {
12 int i,j,k,p,x;
13 i=j=k=p=1;
14 for(x=2;x<=5842;x++)
15 {//算法核心:每次选出最小的值作为因子数,然后其对应的min中的map值被替换成下一个因子数(按升序)
16 map[x]=min( map[i]*2,map[j]*3,map[k]*5,map[p]*7);
17 if(map[x]==map[i]*2) i++;
18 if(map[x]==map[j ]*3) j++;
19 if( map[ x]==map[k]*5) k++;
20 if(map[x]==map[p]*7) p++;
21 }
22 }
23 int main( )
24 {
25 int n;
26 map[ 1]=1;
27 humble( );//打表
28 while( scanf("%d",&n)&&n)
29 {//特别注意输出格式控制
30 if(n%10==1&&n%100!=11) cout<<"The "<<n<<"st humble number is "<<map[n]<<"."<<endl;
31 if(n%10==2&&n%100!=12 ) cout<<"The "<<n<<"nd humble number is "<<map[n]<<"."<<endl;
32 if(n%10==3&&n%100!=13) cout<<"The "<<n<<"rd humble number is "<<map[n]<<"."<<endl;
33 if( n%10>=4||n%10==0) cout<<"The "<<n<<"th humble number is "<<map[n]<<"."<<endl;
34 if( n%100==11||n%100==12||n%100==13) cout<<"The "<<n<<"th humble number is "<<map[n]<<"."<<endl;
35 }
36 return 0;
37 }