算法题(228):treats for the cows
审题:
本题需要我们通过使用最佳售卖方法,让我们卖出东西收到的钱是最多的,并把最多的钱数打印出来
思路:
方法一:动态规划本题限制我们只能从左右端点中选择食品售卖,所以我们可以考虑用区间dp
(1)状态表示:
f[i][j]表示区间[i,j]的范围内售卖所得到的最大价值
(2)状态转移方程:
由于只能售卖两个端点,所以我们分两种情况
情况1:售卖第i个位置的物品
由于题目中说物品最终售卖价值是:v[i]xday,所以我们需要先将天数求出,而天数等于物品售卖编号,就是说当前物品是第几个被售卖的就是第几天被卖的。
(总个数减去还未售卖的物品数,可以得到已经卖出的物品数,加一之后就是当前物品的编号,也是天数)
故:day = n - len + 1
那么售卖第i个物品的价值就是v[i]*day,然后再加上[i+1,j]区间的f值即可
情况2:售卖第j个位置的物品
同理可得
(3)初始化:
全部初始化为0即可,因为在i>j的情况中,值为0不会影响结果的正常计算。结果的计算依赖的是max函数,而正常值都是大于0的,所以0不会影响结果
(4)填表顺序:
我们还是用区间dp的填表方法,第一层用len,第二层用i(需要注意i+len-1<=n)(5)答案输出:
直接输出f[1][n],表示区间[1,n]的最大售卖价值解题:
#include<iostream> using namespace std; const int N = 2e3 + 10; int n; int v[N]; int f[N][N]; int main() {cin >> n;for (int i = 1; i <= n; i++){cin >> v[i];}//填表for (int len = 1; len <= n; len++){for (int i = 1; (i + len - 1) <= n; i++){int j = i + len - 1;int day = n - len + 1;f[i][j] = max(f[i + 1][j] + v[i] * day, f[i][j - 1] + v[j] * day);}}//答案输出cout << f[1][n] << endl;return 0; }
P2858 [USACO06FEB] Treats for the Cows G/S - 洛谷