题目大意
农场的栅栏年久失修,出现了多处破损,晶晶准备维修它,栅栏是由 n n n 块木板组成的,每块木板可能已经损坏也可能没有损坏。晶晶知道,维修连续 m m m 个木板(这 m m m 个木板不一定都是损坏的)的费用是 m \sqrt{m} m。可是,怎样设计方案才能使总费用最低呢?请你写程序帮忙计算。
输入格式
第一行包含一个整数
n
n
n(
n
<
=
2500
n<=2500
n<=2500),表示栅栏的长度。
第二行包含n个由空格分开的整数(
−
1000
-1000
−1000~
1000
1000
1000 ),如果第
i
i
i 个数是
0
0
0,则表示第i块木板已经损坏,否则表示没损坏。
输出格式
一个实数,表示最小维修费用。
注意:答案精确到小数点后3位。
输入样例
9
0 -1 0 1 2 3 0 -2 0
输出样例
3.000
基本思路
这题是个明显的区间 D P DP DP ,但是不能枚举区间进行循环,会超时。因为我们只需要维修坏掉的木板,所以我们可以只记录木板的位置,以维修到第几块木板为阶段。
核心代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2510;
int n,a[N],cnt,t;
double f[N];
int main(){
// 我们只需要维修损坏的板,所以只针对损坏的板进行考虑
// 完全可以以损坏的板为边界,完好的就越过它
// 阶段就是第i块板了
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&t);
if(t==0)
a[++cnt]=i;//记录损坏的板的位置
f[i]=10000;
}
for(int i=1;i<=cnt;i++){
for(int j=i;j>=1;j--)
f[i]=min(f[i],f[j-1]+sqrt(a[i]-a[j]+1));
}
printf("%.3f",f[cnt]);
return 0;
}