题目大意:
给出 N N N 个 p i e pie pie , M M M 头牛,
每头奶牛都有一个吃派的范围和体重,
分别用 l l l , r r r , w w w 表示。
问每头牛吃完后,
在每头牛都吃到至少一个派的情况下最大体重值和
思路:
依题意,每头奶牛都是按区间的方式吃草。
所以我们考虑使用区间dp.
设 f [ i ] [ j ] f[i][j] f[i][j] 表示第 i i i 个 p i e pie pie 到 第 j j j 个 p i e pie pie 之间
全部吃完, 所能贡献的最大体重和。
怎样考虑转移?
普通的转移方程:
f
[
i
]
[
j
]
=
m
i
n
i
≤
k
<
j
(
f
[
i
]
[
k
]
,
f
[
k
+
1
]
[
j
]
)
f\lbrack i\rbrack\lbrack j\rbrack\;=\;\underset{i\leq k<j}{min}(f\lbrack i\rbrack\lbrack k\rbrack,\;f\lbrack k\;+\;1\rbrack\lbrack j\rbrack)
f[i][j]=i≤k<jmin(f[i][k],f[k+1][j])
它实现了两两区间的合并,
但是并没有使得新的奶牛进来吃草。
所以我们考虑在 i ∼ j i\sim j i∼j 中枚举一个点 k k k。
使 k k k 为新牛吃草的点。
即得出方程:
f [ i ] [ j ] = m a x i ≤ k < j ( f [ i ] [ j ] , f [ i ] [ k − 1 ] + d i s [ k ] [ i ] [ j ] + f [ k + 1 ] [ j ] ) \underset{\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;i\leq k<j}{f\lbrack i\rbrack\lbrack j\rbrack\;\;=max}(f\lbrack i\rbrack\lbrack j\rbrack,\;\;f\lbrack i\rbrack\lbrack k\;-\;1\rbrack\;+\;dis\lbrack k\rbrack\lbrack i\rbrack\lbrack j\rbrack\;+\;f\lbrack k\;+\;1\rbrack\lbrack j\rbrack) i≤k<jf[i][j]=max(f[i][j],f[i][k−1]+dis[k][i][j]+f[k+1][j])
设 d i s [ k ] [ i ] [ j ] dis[k][i][j] dis[k][i][j] 表示当 k k k 新来的牛吃掉 k k k
且 i ≤ l ≤ k ≤ r ≤ j i\le l\le k\le r\le j i≤l≤k≤r≤j 的最大体重;
dis值然后求?
建议大家先去康康此题:涂色
我们根据涂色的思路,每次多图一个点。
那在该题中,dis的值可以考虑每次由
区间 i ∼ j i\sim j i∼j 转移到 i − 1 ∼ j i-1\sim j i−1∼j 和 i ∼ j + 1 i\sim j + 1 i∼j+1
即:
d
i
s
[
k
]
[
i
−
1
]
[
e
n
d
]
=
m
a
x
(
d
i
s
[
k
]
[
i
−
1
]
[
e
n
d
]
,
d
i
s
[
k
]
[
i
]
[
e
n
d
]
)
;
dis[k][i - 1][end] = max(dis[k][i - 1][end], dis[k][i][end]);
dis[k][i−1][end]=max(dis[k][i−1][end],dis[k][i][end]);
d i s [ k ] [ i ] [ e n d + 1 ] = m a x ( d i s [ k ] [ i ] [ e n d + 1 ] , d i s [ k ] [ i ] [ e n d ] ) ; dis[k][i][end + 1] = max(dis[k][i][end + 1], dis[k][i][end]); dis[k][i][end+1]=max(dis[k][i][end+1],dis[k][i][end]);
Final node:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
#define ll long long
using namespace std;
const int MAX = 2147483647;
const int N = 310;
int n, m, w, l, r, dis[N][N][N],f[N][N];
int main(){
scanf("%d%d", &n, &m);
for(register int i=1;i<=m;i++){
scanf("%d%d%d", &w, &l, &r);
for(int j = l; j <= r; j++) dis[j][l][r] = max(dis[j][l][r], w);
}
for(int len = 1; len <= n; len++)
for(int i = 1; i + len - 1 <= n; i++)
{
int end = i + len - 1;
for(int k = i; k <= end; k++)
{
if(i > 1) dis[k][i - 1][end] = max(dis[k][i - 1][end], dis[k][i][end]);
if(end < n) dis[k][i][end + 1] = max(dis[k][i][end + 1], dis[k][i][end]);
}
}
for(int len = 1; len <= n; len++)
for(int i = 1; i + len - 1 <= n; i++)
{
int end = i + len - 1;
for(int k = i; k <= end; k++)
f[i][end] = max(f[i][end], f[i][k - 1] + dis[k][i][end] + f[k + 1][end]);
}
printf("%d\n", f[1][n]);
return 0;
}
本文介绍了一种使用区间动态规划解决特定问题的方法。问题背景涉及多头牛在一个派范围内进食,目标是在确保每头牛至少吃到一个派的前提下,最大化它们的总体重。文章详细阐述了状态定义、状态转移方程,并提供了完整的代码实现。

324

被折叠的 条评论
为什么被折叠?



