奶牛吃草
问题描述
在X轴上,用一个整树表示坐标。题目给定一个坐标表示奶牛起始位置,再给定一组坐标表示青草的位置,给出一个设定:每过一个单位时间,青草口感损失1个单位。
假定奶牛运行速度就是一个单位/单位时间,忽略奶牛吃草的时间,并且要求奶牛吃掉所有青草,问最小青草损失口感为多少。
输入格式
第一行两个用空格隔开的整数 n,k,分别表示青草的数目和奶牛的初始坐标。
第 2 行到第 n+1 行,第 i+1 行有一个整数 x[i],描述第 i 棵青草的坐标。
输出格式
一行一个整数,表示吃掉所有青草的前提下,最小损失的口感之和。保证答案在 32 位有符号整数的范围内。
样例输入
4 10
1
9
11
19
样例输出
44
样例解释
先跑到 9,然后跑到 11,再跑到 19,最后到 1,可以让损失的口感总和为 29+1+3+11=44。可以证明不存在比这更优的解。
代码实现
#include <bits/stdc++.h>
using namespace std;
// ================= 代码实现开始 =================
/* 请在这里设计你的算法 */
const int N = 2003;
int dp[N+2][N+2][2];
// 本函数求解答案(损失的最小口感和)
// n:青草棵数
// k:奶牛的初始坐标
// x:描述序列 x(这里需要注意的是,由于 x 的下标从 1 开始,因此 x[0] 的值为 -1,你可以忽略它的值,只需知道我们从下标 1 开始存放有效信息即可),意义同题目描述
// 返回值:损失的最小口感和
int getAnswer(int n, int k, vector<int> x) {
/* 请在这里设计你的算法 */
sort(x.begin()+1, x.end());
for(int i=1; i<=n; ++i)//只吃一棵草
dp[i][i][0] = dp[i][i][1] = abs(x[i] - k) * n;
for(int len=1; len<n; ++len){
for(int L=1, R; (R=L+len)<=n; ++L){ //[L,R]表示已被吃掉的草的连续区间
dp[L][R][0] = min(dp[L+1][R][0] + (n-(R-L)) * abs(x[L] - x[L+1]),//原本在左,继续向左吃
dp[L+1][R][1] + (n-(R-L)) * abs(x[L] - x[R])); //原本在右,跑到左来吃
dp[L][R][1] = min(dp[L][R-1][1] + (n-(R-L)) * abs(x[R] - x[R-1]),//原本在右,继续向右吃
dp[L][R-1][0] + (n-(R-L)) * abs(x[R] - x[L])); //原本在左,跑到右来吃
}
}
return min(dp[1][n][0], dp[1][n][1]);
}
// ================= 代码实现结束 =================
int main() {
int n, k, tmp;
vector<int> x;
scanf("%d%d", &n, &k);
x.clear();
x.push_back(-1);
for (int i = 1; i <= n; ++i) {
scanf("%d", &tmp);
x.push_back(tmp);
}
int ans = getAnswer(n, k, x);
printf("%d\n", ans);
return 0;
}
来源
来自邓俊辉老师的《算法训练营》第一期。