洛谷P5851 [USACO19DEC]Greedy Pie Eaters P 题解

洛谷P5851 [USACO19DEC]Greedy Pie Eaters P 题解

题目链接:P5851 [USACO19DEC]Greedy Pie Eaters P

题意

Farmer John 有 M M M 头奶牛,为了方便,编号为 1 , … , M 1,\dots,M 1,,M。这些奶牛平时都吃青草,但是喜欢偶尔换换口味。Farmer John 一天烤了 N N N 个派请奶牛吃,这 N N N 个派编号为 1 , … , N 1,\dots,N 1,,N。第 i i i 头奶牛喜欢吃编号在 [ l i , r i ] \left[ l_i,r_i \right] [li,ri] 中的派(包括两端),并且没有两头奶牛喜欢吃相同范围的派。第 i i i 头奶牛有一个体重 w i w_i wi,这是一个在 [ 1 , 1 0 6 ] \left[ 1,10^6 \right] [1,106] 中的正整数。

Farmer John 可以选择一个奶牛序列 c 1 , c 2 , … , c K c_1,c_2,\dots,c_K c1,c2,,cK,并让这些奶牛按这个顺序轮流吃派。不幸的是,这些奶牛不知道分享!当奶牛 吃派时,她会把她喜欢吃的派都吃掉——也就是说,她会吃掉编号在 [ l c i , r c i ] [l_{c_i},r_{c_i}] [lci,rci] 中所有剩余的派。Farmer John 想要避免当轮到一头奶牛吃派时,她所有喜欢的派在之前都被吃掉了这样尴尬的情况。因此,他想让你计算,要使奶牛按 c 1 , c 2 , … , c K c_1,c_2,\dots,c_K c1,c2,,cK 的顺序吃派,轮到这头奶牛时她喜欢的派至少剩余一个的情况下,这些奶牛的最大可能体重( w c 1 + w c 2 + … + w c K w_{c_1}+w_{c_2}+\ldots+w_{c_K} wc1+wc2++wcK)是多少。

显然是一个区间dp

f [ i ] [ j ] f[i][j] f[i][j] 表示吃完 [ i , j ] [i,j] [i,j] 能获得的最大 ∑ w \sum w w

g [ k ] [ i ] [ j ] g[k][i][j] g[k][i][j] 表示 k k k 还没吃,准备吃掉 k k k ( i ≤ l d ≤ k ≤ r d ≤ j ) (i \le l_d \le k \le r_d \le j) (ildkrdj) 的最大 w w w

首先不尝试增加奶牛 d d d ,即不考虑吃 k k k ,有
f [ i ] [ j ] = max ⁡ ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] ) f[i][j]=\max(f[i][j],f[i][k]+f[k+1][j]) f[i][j]=max(f[i][j],f[i][k]+f[k+1][j])

考虑吃 k k k ,尝试增加奶牛 d d d ,有
f [ i ] [ j ] = max ⁡ ( f [ i ] [ j ] , f [ i ] [ k − 1 ] + f [ k + 1 ] [ j ] + g [ k ] [ i ] [ j ] ) f[i][j]=\max(f[i][j],f[i][k-1]+f[k+1][j]+g[k][i][j]) f[i][j]=max(f[i][j],f[i][k1]+f[k+1][j]+g[k][i][j])

  • 关于 g [ k ] [ i ] [ j ] g[k][i][j] g[k][i][j] 如何限制 ( l d ≤ k ≤ r d ) (l_d \le k \le r_d) (ldkrd)

    考虑读入时处理每头奶牛 g [ t ] [ l ] [ r ] = w , l ≤ t ≤ r g[t][l][r]=w,l \le t \le r g[t][l][r]=w,ltr

  • 如何更新 g [ k ] [ i ] [ j ] g[k][i][j] g[k][i][j]

    显然当 [ i , j ] = [ l d , r d ] [i,j]=[l_d,r_d] [i,j]=[ld,rd] 时,已经在读入时更新了

    i ≤ l d i \le l_d ild j ≥ r d j \ge r_d jrd 时,我们可以通过
    g [ k ] [ i − 1 ] [ j ] = max ⁡ ( g [ k ] [ i − 1 ] [ j ] , g [ k ] [ i ] [ j ] ) g [ k ] [ i ] [ j + 1 ] = max ⁡ ( g [ k ] [ i ] [ j + 1 ] , g [ k ] [ i ] [ j ] ) g[k][i-1][j]=\max(g[k][i-1][j],g[k][i][j]) \\g[k][i][j+1]=\max(g[k][i][j+1],g[k][i][j]) g[k][i1][j]=max(g[k][i1][j],g[k][i][j])g[k][i][j+1]=max(g[k][i][j+1],g[k][i][j])
    进行更新

时间复杂度 O ( n 3 ) O(n^3) O(n3)

代码:

#include <bits/stdc++.h>
using namespace std;
// #define int long long
// #define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(305)
#define M (int)(5e4+15)
int n,m;
int f[N][N],g[N][N][N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n >> m;
    for(int i=1,w,l,r; i<=m; i++)
    {
        cin >> w >> l >> r;
        for(int j=l; j<=r; j++)
            g[j][l][r]=w;
    }
    for(int len=1; len<=n; len++)
        for(int i=1,j=i+len-1; j<=n; i++,j++)
            for(int k=i; k<=j; k++)
            {
                if(i!=1)g[k][i-1][j]=max(g[k][i-1][j],g[k][i][j]);
                if(j!=n)g[k][i][j+1]=max(g[k][i][j+1],g[k][i][j]);
            }
    for(int len=1; len<=n; len++)
        for(int i=1,j=i+len-1; j<=n; i++,j++)
        {
            for(int k=i; k<j; k++)
                f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
            for(int k=i; k<=j; k++)
                f[i][j]=max(f[i][j],(k!=i?f[i][k-1]:0)+(k!=j?f[k+1][j]:0)+g[k][i][j]);
        }
    cout << f[1][n];
    return 0;
}

转载清说明出处

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值