標籤:
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),為每個村莊的感染人數
Output
輸出一個整數,表示在治癒所有村民前最少的死亡人數。
Sample Input6
40 200 1 300 2 10Sample Output1950HINT
100%的資料,n<=3000
題解:設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(n2)PS:這也是jsoi2016R2D2T1code:
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 }
bzoj4038: 醫學援助