洛谷1107 雷涛的小猫

  • dp(i, j): 第i棵树,j高度可以吃到的果子数量——第j高度的果子也被吃了
  • dp(i, j) = max(dp(i, j-1)+a(i, j), dp(k, j-delta)+a(i, j)) ( kN k ∈ N except i)
  • 因为j-delta是固定的,所以可以预处理出第j高度的dp最大值来减小复杂度——在代码中是g数组,g[i]代表第i高度的dp最大值
#include 
#include 
#include 
#include 
using namespace std;

int data[2010][2010];// data[i][j], 第i棵树第j高度有data[i][j]个果子
long long dp[2010][2010];
long long g[2010];

long long MAX(long long x, long long y) { return x > y ? x : y; }
int main() {
    memset(data, 0, sizeof(data));
    int N, H, Delta;
    scanf("%d%d%d", &N, &H, &Delta);
    int tmp1, tmp2;
    for (int i = 0; i < N; i++) {
        scanf("%d", &tmp1);
        for (int j = 0; j < tmp1; j++) {
            scanf("%d", &tmp2);
            data[i][tmp2]++;
        }
    }
    memset(dp, 0, sizeof(dp));
    memset(g, 0, sizeof(g));
    for (int i = 1; i <= H; i++) {
        for (int j = 0; j < N; j++) {
            if (i > Delta) {
                dp[i][j] = MAX(dp[i - 1][j] + data[j][i], g[i - Delta] + data[j][i]);
                g[i] = MAX(g[i], dp[i][j]);
            } else {
                dp[i][j] = dp[i - 1][j] + data[j][i];
                g[i] = MAX(g[i], dp[i][j]);
            }
        }
    }
    long long ans = 0;
    for (int i = 0; i < N; i++) {
        ans = ans <= dp[H][i] ? dp[H][i] : ans;
    }
    printf("%lld\n", ans);
}

可以使用一维数组

#include 
#include 
#include 
#include 
using namespace std;


int data[2010][2010];// data[i][j], 第i棵树第j高度有data[i][j]个果子
long long dp[2010];
long long g[2010];

long long MAX(long long x, long long y) { return x > y ? x : y; }
int main() {
    memset(data, 0, sizeof(data));
    int N, H, Delta;
    scanf("%d%d%d", &N, &H, &Delta);
    int tmp1, tmp2;
    for (int i = 0; i < N; i++) {
        scanf("%d", &tmp1);
        for (int j = 0; j < tmp1; j++) {
            scanf("%d", &tmp2);
            data[i][tmp2]++;
        }
    }
    memset(dp, 0, sizeof(dp));
    memset(g, 0, sizeof(g));
    for (int i = 1; i <= H; i++) {
        for (int j = 0; j < N; j++) {
            if (i > Delta) {
                dp[j] = MAX(dp[j] + data[j][i], g[i - Delta] + data[j][i]);
                g[i] = MAX(g[i], dp[j]);
            } else {
                dp[j] = dp[j] + data[j][i];
                g[i] = MAX(g[i], dp[j]);
            }
        }
    }
    long long ans = 0;
    for (int i = 0; i < N; i++) {
        ans = ans <= dp[i] ? dp[i] : ans;
    }
    printf("%lld\n", ans);
}

你可能感兴趣的:(ACM,算法)