版权声明:欢迎借鉴,禁止ctrl+c,只可以点击[复制] https://blog.csdn.net/hunkwu/article/details/91043749
题目:
农场的栅栏年久失修,出现了多处破损,晶晶准备维修它,栅栏是由n块木板组成的,每块木板可能已经损坏也可能没有损坏。晶晶知道,维修连续m个木板(这m个木板不一定都是损坏的)的费用是sqrt(m)。可是,怎样设计方案才能使总费用最低呢?请你写程序帮忙计算。
输入:
第一行包含一个整数n(n<=2500),表示栅栏的长度。
第二行包含n个由空格分开的整数(-1000~1000),如果第i个数是0,则表示第i块木板已经损坏,否则表示没损坏。
输出:
一个实数,表示最小维修费用。
注意:答案精确到小数点后3位。
样例输入:
9
0 -1 0 1 2 3 0 -2 0
样例输出:
3.000
思路:
DP。判断是不是0,不是0证明没被损坏,就求前缀和,然后DP
设f[i]为前i个最小的花费,则动态转移方程为:
:
#include<cstdio>
#include<cmath>
#define lb long double
int n,a[100000];
lb f[1000001];
lb min(lb x,lb y)
{
if(x<y)return x;
return y;
}//最小值
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
f[0]=0;//初始化
for(int i=1;i<=n;i++)//栅栏数
{
f[i]=0x7f;//初始化
if(a[i]!=0)f[i]=f[i-1];//前缀和
for(int j=0;j<i;j++)
{
int m=i-j;//题目中的m
f[i]=min(f[i],f[j]+sqrt(m));
}
}
printf("%.3lf",f[n]);
}