bzoj4038: 醫療援助

Description

一隻帶着先進設備和藥物的醫療團隊來到了埃博拉病毒疫區的某個非洲國家。這個國家有n個村莊,均坐落在該國惟一的一條公路旁,n個村莊依次標號爲1,2,…n。第i個村莊有a_i個埃博拉感染者。
到來後的第一天早晨,醫療團隊在第1個村莊。天天他們能夠選擇治療所在村莊的村民,這樣全部感染者都會痊癒;他們也能夠選擇前往相鄰的一個村莊,路程須要1天。天天結束時,若是第i個村莊的a_i個感染者沒有痊癒,那麼他們會死去,同時會有另外a_i我的被感染。也就是說,若是第i個村莊沒有被治療,那麼天天這個村莊會死去a_i我的。
醫療團隊在通過村莊i時,可能選擇不治療這個村莊而前往下一個村莊i+1。但爲了避免讓村民失去但願,若是醫療團隊在村莊j決定往回走時,則他們要治療村莊j以前全部沒有被治療的村莊,同時在返回的過程當中,若是通過沒有接受治療的村莊,他們須要停下來進行治療。
醫療團隊最終會治癒全部村民。做爲團隊的領導人,你須要得出在合理規劃行程下最少的死亡人數。
 
 

 

Input

第一行爲一個正整數n,表示村莊的個數。接下來一行是n個正整數a_i(1<=a_i<=10^9),爲每一個村莊的感染人數ios

 

Output

輸出一個整數,表示在治癒全部村民前最少的死亡人數。git

 

Sample Input

6
40 200 1 300 2 10

Sample Output

1950

HINT

 

100%的數據,n<=3000spa

 

題解:
設g[i][j]表示從j開始走,走到i,而後回頭到j,i到j之間的村子的最小死亡人數
顯然g[i][i]=0
考慮j這個村子一開始是治療仍是被跳過
因此g[i][j]=g[i][j+1]+sum[j+1,i]+min((i-j)*3*a[j],sum[j+1,i])
而後設f[i]表示走到i,且前面的都治好了的狀況下,總共的最小死亡人數
轉移就是枚舉j,考慮從j+1出發到i,而後回頭到j+1,再回頭到i
即f[i]=min{f[j]+g[i][j+1]+sum[i+1,n]*((i-j)*4-2)}
複雜度O(n 2)
PS:這也是jsoi2016R2D2T1
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long int64;
 8 char ch;
 9 bool ok;
10 void read(int &x){
11     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
12     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
13     if (ok) x=-x;
14 }
15 void read(int64 &x){
16     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
17     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
18     if (ok) x=-x;
19 }
20 const int maxn=3005;
21 int n;
22 int64 a[maxn],sum[maxn],g[maxn][maxn],f[maxn];
23 inline int64 s(int l,int r){return sum[r]-sum[l-1];}
24 int main(){
25     read(n);
26     for (int i=1;i<=n;i++) read(a[i]);
27     for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
28     for (int i=1;i<=n;i++){
29         g[i][i]=0;
30         for (int j=i-1;j>=1;j--) g[i][j]=g[i][j+1]+s(j+1,i)+min(3LL*(i-j)*a[j],s(j+1,i));
31     }
32     memset(f,63,sizeof(f));
33     f[0]=0;
34     for (int i=1;i<=n;i++) for (int j=0;j<i;j++) f[i]=min(f[i],f[j]+g[i][j+1]+s(i+1,n)*(4LL*(i-j)-2));
35     printf("%lld\n",f[n]);
36     return 0;
37 }
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息