1 条题解
-
0
解题思路
问题分析:
这是一个典型的动态规划问题,类似于矩阵链乘法或石子合并问题。由于地块是环形排列的,我们需要将其拆解为线性问题进行处理。通常的方法是复制数组,将环形问题转化为线性问题。每次分割的代价是分割后两部分中较大的面积乘以系数F,目标是找到分割顺序使得总代价最小。
动态规划状态定义:
定义表示将区间的地块分割成单独地块的最小总代价。初始状态:,因为单个地块无需分割。状态转移:对于区间,枚举所有可能的分割点k,将区间分为和,则分割代价为,总代价为。
环形处理:
将原数组复制一份接在原数组后面,形成长度为的数组。对每个可能的起点,计算,取最小值作为答案。
前缀和优化:
使用前缀和数组快速计算区间和,=∑(从到)。
解题方法
输入处理:
读取和,如果=且,则结束程序。读取地块面积数组,并将其复制一份接在后面,形成长度为的数组。
初始化:
初始化前缀和数组,其中。初始化动态规划数组,其中。
动态规划填表:
按区间长度从小到大进行遍历,从到。对于每个区间,枚举所有可能的分割点k,计算分割后的代价,并更新。
求解最小值:
遍历所有可能的起点,计算,取最小值作为答案。输出最小值乘以,保留两位小数
C++代码实现:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int dp[410][410],val[410],s[410],INF=1e9; int main() { int n,N,i,j,k,len,ans; double p; while(~scanf("%d%lf",&n,&p) && n) { for(i=1;i<=n;i++) { scanf("%d",&val[i]); val[i+n]=val[i]; } N=n*2; for(i=1;i<=N;i++) { dp[i][i]=0; s[i]=s[i-1]+val[i]; } for(len=1;len<n;len++) for(i=1;i+len<=N;i++) { j=i+len; dp[i][j]=INF; for(k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+max(s[k]-s[i-1],s[j]-s[k])); } ans=INF; for(i=1;i<=n;i++) ans=min(ans,dp[i][i+n-1]); printf("%.2f\n",ans*p); } }
- 1
信息
- ID
- 1087
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者