动态规划--免费馅饼


由数塔引出。

数塔:

处于一个端点,每次可以选择向左或向右。

而每次选择,取决于,向左能够得到最大值,还是向右能得到最大值。

当到达数塔倒数第二行时,向左还是向右,仅仅取决于,向左的端点数值大还是向右的大。

自顶向下思考,自底向上计算。

将数塔倾斜,用i,j表示在数塔中位置,dp[ i ][ j ]则表示在为位置( i , j )时,能够得到的最大值。

得到 1.递推公式 dp[ i ][ j ] = max(dp[ i + 1 ][ j ],dp[ i ][ j + 1 ]) + num[ i ][ j ];

2.边界条件 dp[ n - j + 1][ j ]  = num[ j ] ( j = 1 to n )

//即dp[n][0] = num[0],dp[n - 1][1] = num[1]...

免费馅饼 hdu1176

假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问gameboy最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼)

输入数据有多组。每组数据的第一行为以正整数n(0<n<100000),表示有n个馅饼掉在这条小径上。在结下来的n行中,每行有两个整数x,T(0<T<100000),表示在第T秒有一个馅饼掉在x点上。同一秒钟在同一点上可能掉下多个馅饼。n=0时输入结束。

表示gameboy最多接到几个馅饼?

分析:

处于一个位置,每次可以选择向左,向右,或者不动。

每次的选择,依然取决于,向左,向右,不动,哪个选择能使,达到最大值。

当时间在倒数第二秒时,每次选择,仅取决于,下一秒,3个位置中的哪个位置,会得到最大值。

仍然用i,j表示在这个树中的位置,i 表示位置(0 ~ 10),j表示时间,dp[ i ][ j ]表示,在时间j,位置i所能得到的最大值。

得到 1.递推公式 dp[ i ][ j ] = max(dp[ i - 1][ j + 1 ],dp[ i ][ j + 1 ],dp[ i + 1 ][ j + 1 ]) + 在时刻j,位置i所落下的馅饼数

//注意i,j不要越界

2.边界条件 dp[ i ][ last_time ] = 在last_time最后一刻,位置i落下的馅饼数



#include <iostream>

#include <cstdio>

#include <map>

#include <vector>

#include <cstring>

using namespace std;

const int maxt = 100005;

int dp[12][maxt];

void solve(int last_time,map<int, vector<int>> &mp)

{

    for (int j = last_time; j >= 0; j --) {

        vector<int> &v = mp[j];

        if (j == last_time) {

            for (int k = 0; k < v.size(); k ++) {

                dp[v[k]][j] ++;

            }

        }

        else {

            for (int i = 0; i <= 10; i ++) {

                if (i == 0) {

                    dp[i][j] = max(dp[i][j + 1],dp[i + 1][j + 1]);

                }

                else if(i == 10)

                    dp[i][j] = max(dp[i][j + 1],dp[i - 1][j + 1]);

                else dp[i][j] = max(dp[i][j + 1], max(dp[i + 1][j + 1],dp[i - 1][j + 1]));

            }

            for (int k = 0; k < v.size(); k ++) {

                dp[v[k]][j] ++;

            }

        }

    }

}

int main()

{

    int n;

    int x,t;

    while (scanf("%d",&n) != EOF && n) {

        map<int, vector<int>> mp;

        memset(dp, 0, sizeof(dp));

        int last_time = 0;

        for (int i = 0; i < n; i ++) {

            scanf("%d%d",&x,&t);

            last_time = max(last_time, t);

            mp[t].push_back(x);

        }

        solve(last_time, mp);

        printf("%d\n",dp[5][0]);

    }

    return 0;

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值