HDU4734 F(x)

数位DP

讲一下具体思路,自己是看了kuangbin的板子来做的

DP的关键在于如何去寻找转移方程,本道题用到了一种相减的思路

A,B分别代表题目描述的变量

DP[pos][sum] pos 不用多说就是数位, sum这里不是指一个数的和,这里的sum指的是距离凑满F(A)还需要多少数这样子转移方程就可以记忆化了,为什么呢?当第一步的时候指的是DP[pos][F(A)],但是继续往下dfs,因为每一步都要减去一个数,这个时候sum,更新成了一个新的数字,这个时候我们求得就是距离凑满新的sum还需要多少的数,这样就跟F(A)相当于脱离了,每一个求出来的DP[][]是可以作用于所有的数的如果还不明白可以自己在程序上做几个测试点帮助自己理解,只要记住DP[pos][sum]求的是在pos位,距离凑满sum的数有多少就行

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int case_ = 0;
int dp[20][6000];
int p[20];
int dfs(int pos, int sum, bool limit){
    if(sum < 0) return 0;
    if(pos == -1 && sum >= 0) return 1;
    if(!limit && dp[pos][sum] != -1) return dp[pos][sum];
    int up = limit? p[pos]: 9;
    int ans = 0;
    for(int i = 0; i <= up; i++){
        ans += dfs(pos-1, sum - i*(1<<pos), limit && i==p[pos]);
    }
    if(!limit) dp[pos][sum] = ans;
    return ans;
}
int F(int x){
    int sum = 0;
    int len = 0;
    while(x){
        sum += (x%10)*(1<<len);
        len++;
        x /= 10;
    }
    return sum;
}
int solve(int y, int x){
    int len = 0;
    while(x){
        p[len++] = x%10;
        x /= 10;
    }
    return dfs(len-1, F(y), true);
}
int main()
{
    int TestCase;
    memset(dp, -1, sizeof(dp));
    scanf("%d", &TestCase);
    int A, B;
    while(TestCase--){
        scanf("%d%d", &A, &B);
        printf("Case #%d: %d\n", ++case_, solve(A, B));
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值