[51nod1425]减减数

  初始给定一个整数n。每次可以对其做一个操作,这个操作是将n减去他其中的某一位。得到新的一个数字n’,然后继续操作,直到他变成0为止。
  比如24这个例子,24 → 20 → 18 → 10 → 9 → 0

 Input
  单组测试数据。
  第一行有一个整数n(0 ≤ n ≤ 10^12)
 Output
  输出一个整数表示使得n变成0最少的操作步数。.

 

 

  呃...今年学车中学noi摸你赛某场的T3....怎么在51nod上才5级啊(掀桌

  十连测那时候抄高分代码才过的...现在终于成功乱(背)搞(诵)出来了...

  没见过的数位DP姿势。

  结构体f[i][j][k].step、.rest:更高的位数最大值为j,将10^(i-1)-k变成<=0的最少步数step、变后的数字为-rest(1<=k<=9)

  g[i].step、.rest:将n的最低i位变成<=0的最少步数step、变后的数字为-rest

  然后转移的时候其实就是调若干次f数组,每次把当前位的数字-1。需要特判.rest等于0的情况。具体见代码吧。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cmath>
 7 #include<cstdlib>
 8 #include<bitset>
 9 //#include<ctime>
10 #define ll long long
11 #define ull unsigned long long
12 #define ui unsigned int
13 #define d double
14 //#define ld long double
15 using namespace std;
16 const int maxn=100233;
17 struct zs{ll step;int rest;}f[23][10][10],g[23];
18 int s[23],premx[23];
19 //int ff[233333];ll ten[23];
20 int i,j,k,n,m;
21 
22 int ra,fh;char rx;
23 inline int read(){
24     rx=getchar(),ra=0,fh=1;
25     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
26     if(rx=='-')fh=-1,rx=getchar();
27     while(rx>='0'&&rx<='9')ra=ra*10+rx-48,rx=getchar();return ra*fh;
28 }
29 inline int max(int a,int b){return a>b?a:b;}
30 /*
31 inline void vio(){
32     for(i=1;i<=9;i++)ff[i]=1;
33     for(i=10;i<233333;i++){
34         int mx=0,j=i;
35         while(j)mx=max(mx,j%10),j/=10;
36         ff[i]=ff[i-mx]+1;
37     //    if(i<30)printf("%d   %d\n",i,ff[i]);
38     }
39 }*/
40 int main(){
41 //        vio();
42     ll n;
43     scanf("%lld",&n);int len=0;
44     if(!n)return puts("0"),0;
45     for(ll x=n;x;x/=10)s[++len]=x%10;
46     for(i=/*ten[0]=*/1;i<=len;i++)premx[i]=max(premx[i-1],s[len-i+1]);//,ten[i]=ten[i-1]*10;
47     
48     for(i=0;i<=9;i++)for(j=1;j<10;j++)f[1][i][j]=(zs){1,max(0,i-(10-j))};
49     g[1]=(zs){1,premx[len]-s[1]};
50     
51     register int digit,nrest;ll nstep;zs tmp;
52     for(i=2;i<=len;i++){
53         if(i<len){
54             for(j=0;j<=9;j++)for(k=1;k<10;k++){
55                 for(digit=9,nstep=0,nrest=k;digit>=0;digit--){
56                     tmp=f[i-1][max(j,digit)][nrest],
57                     nstep+=tmp.step,nrest=tmp.rest;
58                     if(!nrest&&digit)nstep++,nrest=max(j,digit);
59                 }
60                 f[i][j][k]=(zs){nstep,nrest};
61                 //if(!j)printf("%d %d %d     (%lld,%d)  ff:%d\n",i,j,k,f[i][j][k].step,f[i][j][k].rest,ff[ten[i]-k]);
62             }
63         }
64         
65         nstep=g[i-1].step,nrest=g[i-1].rest;
66         if(!nrest&&s[i])nstep++,nrest=premx[len-i+1];
67         for(digit=s[i]-1;digit>=0;digit--){
68             tmp=f[i-1][max(premx[len-i],digit)][nrest],
69             nstep+=tmp.step,nrest=tmp.rest;
70             if(!nrest&&digit)nstep++,nrest=max(premx[len-i],digit);
71         }
72         g[i]=(zs){nstep,nrest};
73     }//printf("%lld  %d\n",g[len].step,ff[n]);
74     printf("%lld\n",g[len].step);
75 }
View Code

 

posted @ 2016-10-13 20:02  czllgzmzl  阅读(460)  评论(0编辑  收藏  举报