[ABC 099] C-Strange Bank

C - Strange Bank


Time limit : 2sec / Memory limit : 256MB

Score : 300 points

Problem Statement

To make it difficult to withdraw money, a certain bank allows its customers to withdraw only one of the following amounts in one operation:

  • 1 yen (the currency of Japan)

  • 6 yen, 62(=36) yen, 63(=216) yen, ...

  • 9 yen, 92(=81) yen, 93(=729) yen, ...

At least how many operations are required to withdraw exactly N yen in total?

It is not allowed to re-deposit the money you withdrew.

Constraints

  • 1≤N≤100000
  • N is an integer.

[题目解释]

  现在我们要取出n元钱,每一次取只能取出1,6m,9m(m>0且m为整数)元,问我们最少要取几次?

[题目解析]

  这道题类似于完全背包问题,但不同的是问在刚好取出n元的情况下最小代价为多少,我们可以预处理出一次取钱的所有情况其代价为1,我们记一个数组f[],f[i]表示取出i元最小代价为f[i],由于我们可以1元1元地取,取出i元的最大代价为i(即一定可以恰好取出i元),我们尝试是否能放进其他物品,使其代价更小,若更小就更新答案.方程为f[i]=min(f[i-thing[j]]+1);其中thing[]为预处理出每一次可以取出的钱数;

[代码]

/*
    Name: Strange Bank 
    Author: FZSZ-LinHua
    Date: 2018 06 10
    Exec time: 13ms
    Memory usage: 640KB
    Score: 300
    Algorithm: Dynamic programming
*/
# include "iostream"
# include "cstdio"
# include "cstring" 

using namespace std;

const int maxm=100000+10;
int f[maxm],n;
int thing[maxm],tot; //thing[i]为预处理出每一次可以取出钱的所有情况,一个有tot种 

int main(){
    thing[++tot]=1;    //一次可以取出1元 
    register int i,j;
    memset(f,0x3f,sizeof(f)); //先给f数组赋一个较大值 
    scanf("%d",&n); 
    i=6; 
    while(i<=n){    //枚举6的次幂 
        thing[++tot]=i;
        i*=6; 
    }
    i=9; 
    while(i<=n){    //枚举9的次幂 
        thing[++tot]=i;
        i*=9; 
    }
    f[0]=0; 
    for(i=1;i<=tot;i++){    //完全背包 
        for(j=thing[i];j<=n;j++){ 
            f[j]=min(f[j],f[j-thing[i]]+1); 
        } 
    }
    printf("%d",f[n]); 
    return 0; 
} 

 

posted @ 2018-06-11 10:37  FJ-Frank  阅读(411)  评论(0)    收藏  举报