【DP】维修栅栏

版权声明:欢迎借鉴,禁止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个最小的花费,则动态转移方程为:

f [ i ] = m i n ( f [ i ] , f [ j ] + s q r t ( m ) ) ; f[i]=min(f[i],f[j]+sqrt(m));

C o d e Code

#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]);
	
}

猜你喜欢

转载自blog.csdn.net/hunkwu/article/details/91043749
今日推荐