1 条题解
-
0
题解:奶牛位置调整问题
题目分析
本题要求将奶牛排列在长度为的直线上,使得相邻奶牛之间的距离尽可能均匀(只能为或),并计算最小移动时间。关键在于确定合理的目标位置,使得总移动距离最小。
解题思路
-
确定平均间隔:
总间隔数为,平均间隔。
余数,表示有个间隔需要为,其余为。 -
动态规划预处理左右边界:
l[i]
:第头奶牛可放置的最小位置。r[i]
:第头奶牛可放置的最大位置。
这些边界由平均间隔和余数决定,确保总长度不超过。
-
动态规划求解最小移动时间:
- 状态定义:
f[j]
表示前头奶牛放置在位置时的最小移动时间。 - 状态转移:遍历所有可能的位置,并从前驱状态(或)转移而来。
- 状态定义:
代码解释
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,d,L,a[100500],f[100500],l[100500],r[100500]; int main(){ scanf("%d%d",&n,&L); d=L/(n-1); // 计算平均间隔D for(int i=0;i<n;i++){ scanf("%d",&a[i]); // 计算第i头奶牛可放置的最小位置 l[i]=max(i*d,L-(n-i-1)*(d+1)); // 计算第i头奶牛可放置的最大位置 r[i]=min((i+1)*(d+1),L-(n-i-1)*d); } memset(f,0x3f,sizeof(f)); // 初始化为无穷大 f[0]=a[0]; // 第1头奶牛必须放在位置0 for(int i=1;i<n;i++){ for(int j=r[i];j>=l[i];j--){ int temp=0x3ffffff; // 临时变量,存储前驱状态的最小值 // 检查j-D是否在前驱奶牛的合法范围内 if(j-d>=l[i-1]&&j-d<=r[i-1])temp=f[j-d]; // 检查j-D-1是否在前驱奶牛的合法范围内 if(j-d-1>=l[i-1]&&j-d-1<=r[i-1])temp=min(temp,f[j-d-1]); // 更新当前状态 f[j]=temp+abs(j-a[i]); } } printf("%d\n",f[L]); // 输出最后一头奶牛在位置L时的最小移动时间 }
关键步骤解析
-
计算平均间隔和余数:
,确定基础间隔。 -
预处理左右边界:
l[i]
确保前头奶牛的最小总间隔不小于。r[i]
确保后头奶牛的最大总间隔不超过。
-
动态规划状态转移:
- 对于每头奶牛,遍历其合法位置。
- 从前驱状态或转移,取最小值并加上当前位置的移动距离。
-
结果输出:
最终答案为,即最后一头奶牛放置在位置时的最小移动时间。
复杂度分析
- 时间复杂度:,其中为平均间隔。
- 空间复杂度:,主要用于存储动态规划数组和边界数组。
该算法通过合理的预处理和动态规划,确保在满足约束条件下找到最小移动时间,有效解决了奶牛位置调整问题。
-
- 1
信息
- ID
- 2185
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者