[kuangbin带你飞] - 免费馅饼 + Help Jimmy (逆向DP )

免费馅饼 + Help Jimmy

题目链接: G - 免费馅饼 HDU - 1176

题意

都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标: img

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


思路一

设置一个dp[i].[j] 储存的是第i秒第j格子的最大馅饼数,转移方程就是 dp[i].[j] = Max(dp[i-1].[j-1],dp[i-1].[j],dp[i-1].[j+1]) + A[i].[j];但是这里有个问题因为gameboy每次只能走一个,所以有些位置应该是走不到的,比如dp[1].[1]就不可能走到,我就另外定义了一个ok数组模拟能走的路及 ok[0].[5] = 1, ok[i].[j] = ok[i-1].[j-1]|ok[i-1].[j+1]|ok[i-1].[j];


思路二

这里的要借鉴一下大神的 思路

​ 5 t=0
456 t=1
34567 t=2
2345678 t=3
123456789 t=4
012345678910 t=5
012345678910 t=6

总体来说,这道题就是上面这样的塔数,很明显,第i层的0只能从上一层的0,1中最大的来,倒推的话,也是一样的,第i层的0也只能由下一层的0,1来,(t=5之前实际没有0,因为走不到那,但是我们可以假设有),同理,每行的10也只能有下一行9,10推出来。

———————————————–分割线————————————————

要倒推,要不然没法到达0,5这个点,因为最后需要从0,5出发的


代码

/*
Time : 93
Mem  : 17
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)(j);i <= (int)(k);i ++)
#define per(i,j,k) for(int i = (int)(j);i >= (int)(k);i --)
#define mmm(a,b)   memset(a,b,sizeof(a))
#define sz(x) ((int)(x).size())
#define pb push_back

typedef double db;
typedef long long ll;
const int INF = (int)0x3f3f3f3f;
const int MAXN = (int)13;

int A[100007][MAXN];
int dp[100007][MAXN];
int ok[100007][MAXN];//代表可不可以走
int N;

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    while (cin >> N,N){
        mmm(A,0);
        mmm(ok,0);
        mmm(dp,0);
        int tim,loc;
        int TimMax = 0;
        rep(i,1,N){
            cin >> loc >> tim;
            A[tim][++loc] ++;
            TimMax = max(TimMax,tim);
        }

        ok[0][6] = 1;
        rep(i,1,TimMax){
            rep(j,1,11){
                ok[i][j] = ok[i-1][j-1]|ok[i-1][j+1]|ok[i-1][j];

                if (ok[i][j]){
                    dp[i][j] = max(dp[i-1][j-1],max(dp[i-1][j],dp[i-1][j+1])) + A[i][j];
                }

            }
        }
        int mn = 0;
        rep(i,1,11){
            mn = max(mn,dp[TimMax][i]);
        }
        cout << mn << endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41428565/article/details/80197070
今日推荐