hdu1058 && hdu3199 丑数 (典型DP)

1058 题意:

整体思想是利用已经知道的序列中的元素根据规则去生成新的元素, x * 2, x * 3, x * 5, x * 7.

假设使用数组a[MAX]进行存储这一序列的所有元素, 首先使a[0] = 1, 表示第一个元素是1, 然后利用4个指针(不是内存指针,呵呵), i2 = i3 = i5 = i7 = 0. 每次我们比较 a[i2] * 2, a[i3] * 3, a[i5] * 5, a[i7] * 7 这四个元素的大小, 把最小的放到序列中, 并把对应的指针+1, 直到生成需要的个数.

#include<stdio.h>
#include<string.h>
#define min(e,f) (e)>(f)?(f):(e)
int dp[6000] = { 0, 1 },i2 = 1, i3 = 1, i5 = 1, i7 = 1, cnt = 1, N;
char lst[5][5] = { "th", "st", "nd", "rd" };
int getUp () {
    int t = min ( min ( 2*dp[i2], 3*dp[i3] ), 
                  min ( 5*dp[i5], 7*dp[i7] ) );  
    if ( t == 2*dp[i2] ) ++ i2;
    if ( t == 3*dp[i3] ) ++ i3;
    if ( t == 5*dp[i5] ) ++ i5;
    if ( t == 7*dp[i7] ) ++ i7; 
    return t; 
}
void init () {
    for ( int i = 2; i <= 5842; ++ i ) {
        dp[i] = getUp ();
    }     
}
char * getLst ( int n ) {
     if ( n % 100 != 11 && n % 10 == 1 ) return lst[1];
     else if ( n % 100 != 12 && n % 10 == 2 ) return lst[2];
     else if ( n % 100 != 13 && n % 10 == 3 ) return lst[3];
     else return lst[0];      
}
int main ()
{
	init();
    while ( scanf("%d",&N)!=EOF &&N)
	{
          printf ( "The %d", N );
          printf ( "%s", getLst ( N ) );
          printf ( " humble number is %d.\n", dp[N] );      
    }
    return 0;
} 

 hdu3199 类似的思想,那个数的范围倒是够吓人的

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
__int64 dp[10000];
__int64 p[4],a,b,c,n;
int main()
{
	while(scanf("%d %d %d %d",&p[1],&p[2],&p[3],&n)==4)
	{
		a=b=c=0;
		dp[0]=1;
		for(int i=1;i<=n;i++)
		{
			__int64 t=min(min(p[1]*dp[a],p[2]*dp[b]),p[3]*dp[c]);
			if(t==p[1]*dp[a]) a++;
			if(t==p[2]*dp[b]) b++;
			if(t==p[3]*dp[c]) c++;
			dp[i]=t;
		}
		printf("%I64d\n",dp[n]);
	}
	return 0;
}



			

		
原文地址:https://www.cnblogs.com/nanke/p/2230397.html