HDU 4433 类似于状态压缩的DP

17 篇文章 0 订阅

这题卡了好几个小时,纠结,后来回想一下,其实是自己模型构建能力太弱了,想清楚的话就容易多了

dp[i][j] 表示位置i,j表示i,i + 1,i + 2位置上的值,dp【i】【j】确保1-----i  - 1 的位置已经一一对应,

然后转移的时候就分为上和下,上的话,注意一下,第一位上升A,第二位可以上升B(B <= A) ,第三位可以上升 C(C <= B)(应该不难理解)

下的话,同理,转移的话,自己看下代码,应该蛮好理解的



#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<map>
#include<set>
#include<queue>
#include<cmath>
#define LL long long
#define INF 1 << 25
using namespace std;
const int maxn = 1025;
int dp[maxn][maxn];
char s[maxn],p[maxn];
int main()
{
    while(scanf("%s%s",s + 1,p + 1) !=  EOF)
    {
        int len = strlen(s + 1);
        s[len + 1] = s[len + 2] = s[len + 3] = p[len + 1] = p[len + 2] = p[len + 3] ='0';
        s[len + 4] = p[len + 4] = 0;
        len += 3;
        for(int i = 1; i <= len ; i ++)
            for(int j = 0; j <= 1000; j ++) dp[i][j] = INF;
        int st = (s[1] - '0') * 100 + (s[2] - '0') * 10 + s[3] - '0';
        dp[1][st] = 0;
        for(int i = 1; i <= len - 3 + 1; i ++)
        {
            for(int j = 0; j <= 999; j ++)
            {
                if(dp[i][j] == INF) continue;
                int hun = j / 100;
                int ten = (j - hun * 100) / 10;
                int num = j - hun * 100 - ten * 10;
                int q1 = s[i + 3] - '0';
                int up = (p[i] -'0' + 10 - hun) % 10;//将第i 位转化成对应的数字,然后开始转移
                for(int k = 0;k <= up;k ++)//可以改变第二位
                    for(int v = 0;v <= k;v ++)//改变第三位
                    {
                        int newj = 100 * (ten + k > 9 ? ten + k - 10:ten + k) + 10 * (num + v > 9 ? num + v - 10:num + v) + q1;
                        dp[i + 1][newj] = min(dp[i + 1][newj],dp[i][j] + up);
                    }
                int down = 10 - up;

                for(int k = 0;k <= down;k ++)
                    for(int v = 0;v <= k;v ++)
                    {
                        int newj = 100 * (ten - k < 0 ? ten - k + 10:ten - k) + 10 * (num - v < 0 ? num - v + 10:num - v) + q1;
                        dp[i + 1][newj] = min(dp[i + 1][newj],dp[i][j] + down);
                    }
            }
        }
        int m = (p[len - 2] - '0')* 100 + (p[len - 1] - '0') * 10 + p[len] - '0';
        printf("%d\n",dp[len - 3 + 1][m]);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值