动态规划刷表法

一.先简单讲下什么是填表法,什么是刷表法。

填表法 :就是一般的动态规划,当前点的状态,可以直接用状态方程,根据之前点的状态推导出来。

刷表法:由当前点的状态,更新其他点的状态。需要注意:只用当每个状态所依赖的状态对它的影响相互独立。

二.通过例题看刷表

链接:http://exam.upc.edu.cn/problem.php?id=2383

题意:三个数,T表示最大的饱腹值,A表示吃a可以增加的饱腹值,B表示吃b可以增加的饱腹值。ab都有无穷多个。初始状态是0,可以有一次通过喝水,来使饱腹值减少一半(向下取整)的机会。

分析:首先按照一般的动态规划,会有问题。

为什么不能用填表法?

因为当前状态既与之前的状态有关,又与之后的状态有关。当前的状态与dp[ i – a],dp[i – b],dp[i * 2]有关。所以用刷表法,来直接更新状态。

此题中,喝水后的状态可以在喝水的基础上计算。及可以先计算所有喝水前的状态,再计算所有喝水后的状态。喝水前的状态可以更新喝水后的状态。

另:注意,本题中饱腹值不能超过最大值T

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <string>
#include <algorithm>
#include <list>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
using namespace std;
int dp[5000005][2];
int main()
{
    //freopen("in.txt","r",stdin);
    int p,a,b;
    scanf("%d%d%d",&p,&a,&b);
    dp[0][0] = dp[0][1] = 1;
    for(int j = 0; j < 2; j ++)
    {
        for(int i = 0; i <= p; i ++)
        {
            if(dp[i][j])
            {
                if(i+ a <= p)
                    dp[i + a][j] = 1;
                if(i + b <= p)
                    dp[i + b][j] = 1;
                if(j == 0)
                    dp[i / 2][1] = 1;
            }
        }
    }
 
 
    int ans;
    for(int i = p; i >= 0; i --)
    {
        if(dp[i][0] || dp[i][1])
        {
            ans = i;
            break;
        }
    }
    printf("%d\n",ans);
 
    return 0;
}

    原文作者:动态规划
    原文地址: https://blog.csdn.net/qq_30241305/article/details/52198780
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞