开餐馆 OpenJ_Bailian - 4118 (动态规划 + 滚动数组)

这题还算是一道比较基础的动态规划问题啦, 和01背包问题略有类似, 都需要考虑容量和复杂度优化, 之前定义状态总想着能二维就二维, 现在看来很多时候其实可以直接用一维的思路去定义状态, 反而会简便很多

定义dp[i] : 前i个地点产生的最大利润(题目给出已排序的坐标, 省去了排序)

然后考虑到对于每个地点我们都有选与不选两种操作, 考虑需要再添加一个循环j : 来考虑第j个地点是否会是最优解

切记dp[i]的初始化就是d[i], 也就是到第i个地点至少的利润, 再注意判断相距要大于d

可得状态转移方程: dp[i] = dp{dp[i], dp[j] + d[i] | dp[i] - dp[j] > k}

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 110;

int T, n, k;
int p[maxn], m[maxn];
int dp[maxn]; //在前i个餐馆里取得的最大价值
int solve()
{
    for(int i = 1; i <= n; i++) //i表示第i个餐馆
        for(int j = 1; j < i; j++){ //找到一个最大价值的位置
            if(m[i] - m[j] > k)
                dp[i] = max(dp[i], dp[j]+p[i]);
        }

    int ans = 0;
    for(int i = 1; i <= n; i++)
        ans = max(dp[i], ans);
    return ans;
}

int main()
{
    cin >> T;
    while(T--){
        cin >> n >> k;
        for(int i = 1; i <= n; i++)
            cin >> m[i];
        for(int i = 1; i <= n; i++){
            cin >> p[i];
            dp[i] = p[i];
        }
        cout << solve() << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1097304791/article/details/83719717