维修栅栏【DP】
維修柵欄
題目大意:
有一串?dāng)?shù),要把這一串?dāng)?shù)改成全部非0的,每一次可以更改某一段的全部數(shù)字,但有代價(jià)sqrt(m)sqrt(m)sqrt(m)(m為當(dāng)前子串的長度)
原題:
題目描述
農(nóng)場(chǎng)的柵欄年久失修,出現(xiàn)了多處破損,晶晶準(zhǔn)備維修它,柵欄是由n塊木板組成的,每塊木板可能已經(jīng)損壞也可能沒有損壞。晶晶知道,維修連續(xù)m個(gè)木板(這m個(gè)木板不一定都是損壞的)的費(fèi)用是sqrt(m)??墒?#xff0c;怎樣設(shè)計(jì)方案才能使總費(fèi)用最低呢?請(qǐng)你寫程序幫忙計(jì)算。
輸入
第一行包含一個(gè)整數(shù)n(n<=2500),表示柵欄的長度。
第二行包含n個(gè)由空格分開的整數(shù)(-1000~1000),如果第i個(gè)數(shù)是0,則表示第i塊木板已經(jīng)損壞,否則表示沒損壞。
輸出
一個(gè)實(shí)數(shù),表示最小維修費(fèi)用。
注意:答案精確到小數(shù)點(diǎn)后3位。
輸入樣例
9 0 -1 0 1 2 3 0 -2 0輸出樣例
3.000解題思路:
直接DP,枚舉每一次的子串,如果子串內(nèi)有0那修,否則不修
代碼:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #define ld long double using namespace std; int n,x,b[3000]; ld f[3000]; ld minn(ld aa,ld bb) {if (aa<bb) return aa;return bb; } int main() {scanf("%d",&n);for (int i=1;i<=n;++i){scanf("%d",&x);if (!x) b[i]++;b[i]+=b[i-1];//前綴和}memset(f,0x7f,sizeof(f));f[0]=0;for (int i=1;i<=n;++i){for (int j=0;j<i;++j)if (b[i]==b[j]) f[i]=minn(f[i],f[j]);//判斷有沒有0,沒有直接賦值else f[i]=minn(f[i],f[j]+sqrt((ld)(i-j)));//有則全部改變}printf("%.3Lf",f[n]);return 0; }總結(jié)
- 上一篇: 初一模拟赛总结(2019.6.1)
- 下一篇: 您的电脑需要多少内存您的电脑需要多少内存