1. 程式人生 > >HDU 2089 不要62(數位DP)

HDU 2089 不要62(數位DP)

註意 break 大小 printf bre 表示 += 理解 ini

題意:求[n,m]內所有數字中不出現4也不出現連續62的數的個數。

輸入:n m,多組數據,以0 0結尾。

輸出:符合條件的數的個數。

限制:(0<n≤m<1000000) 時間:1000 ms 空間:32768 kB

分析:我們引入數位DP的應用範圍:求出在給定區間[A,B]內,符合條件P(i)的數i的個數.條件P(i)一般與數的大小無關,而與 數的組成 有關.

本題我們采用打表+遞推的DP思路解題,空間復雜度比記憶化搜索略高,但便於理解。

#include <cstring>
#include <cstdio>
int dp[10][10];//dp[i][j]表示第i位為j時符合條件的數的個數 
void init(){//打表 memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=7;i++) for(int j=0;j<10;j++)//枚舉第i位可能出現的數 for(int k=0;k<10;k++)//枚舉第i-1位可能出現的數 if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k]; } int solve(int n){ //printf("%d********%d*********%d\n",dp[4][2],dp[5][6],dp[5][7]);
int digit[10],len=0,ans=0; while(n>0){ digit[++len]=n%10; n/=10; } digit[len+1]=0; for(int i=len;i;i--){//從高位到低位,每一位ans都加上所有符合條件的值,不重不漏 for(int j=0;j<digit[i];j++) if(j!=4&&!(digit[i+1]==6&&j==2)) ans+=dp[i][j]; if(digit[i]==4||(digit[i]==2
&&digit[i+1]==6)) break;//繼續循環不可能再有符合題意的值,故直接跳出 } return ans; } int main(){ int l,r; init(); while(scanf("%d%d",&l,&r),l){ printf("%d\n",solve(r+1)-solve(l));//區間相減,註意左閉右開 } return 0; }

HDU 2089 不要62(數位DP)