JSOI2016病毒感染

2022-03-20 01:29:40 字數 1857 閱讀 5773

1.題目大意:

有1-n的村莊,每個村莊在不**的情況下每天死 a[ i ] 人,到達乙個村莊可以**或跳過, 若跳過, 再回頭時只能一直走回這個村莊, 然後才能重新往前走,求最少死亡人數。

2.題目分析

我們定義f[ i ]為前 i 個村莊全部治好的最小代價。令j < i, 在 1-i 內列舉回頭點, 因此我們再定義乙個 g[ i ][ j ] 陣列表示從 i 走到 j 再走回 i 的最小代價, 作為輔助陣列, 在dp的時候輔助求出 f[ i ] 的值。

預處理一下字首和 s 陣列

3.動態轉移方程推導

(1) g陣列:

我們列舉起點 i 和 區間長度 j , 則終點為 i + j

若救 i

w[i+1][i+j] + (s[i+j]-s[i])*2;

救 i 花了一天, 從 i 走到 i+1 花了一天,總共耽誤兩天, 死亡人數 為 i+1 到 j 的總人數 乘以 2, 即(s[i+j]-s[i])*2

若跳過 i

w[i+1][i+j] + 3*j*a[i]+s[i+j]-s[i]

從 i 走到 j 再走回 i 並**從 i+1 到 j 的所有村莊, 耗時 3*j 天。 i 村莊死亡 3*j*a[ i ];

從 i 到 i+1 花了一天, 死亡s[i+j]-s[i]

綜上  w[i][i+j] = w[i+1][i+j]+min((s[i+j]-s[i])*2, 3*j*a[i]+s[i+j]-s[i]);

(2)f陣列

列舉終點 i 和 回頭點 j

f[i] = min(f[i], f[j]+w[j+1][i]+(3*(i-j-1)+i-j+1)*(s[n]-s[i]));

從 j+1 走到 i 回到 j+1, 我們還需再到 i ,耗時 3*(i-(j+1))

從·j 走到 j+1 並** j+1 到 i 的所有村莊 耗時 i-j+1(不理解可以自己畫線段圖看一下)

共死亡(3*(i-j-1)+i-j+1)*(s[n]-s[i]))

4.最後附上**

1 #include2 #include3 #include4 #include5 typedef long long ll;

6 using namespace std;

7 const int maxn = 3010;

8 ll a[maxn], s[maxn], f[maxn], w[maxn][maxn];

9 int main()

15 for(int j=1; j19 }

20 memset(f, 0x3f, sizeof(f));

21 f[0] = 0;

22 for(int i=1; i<=n; i++)

26 }

27 printf("%lld\n",f[n]);

28 return 0;

29 }

JSOI 2016 病毒感染 輔助Dp問題

直接看這道題,第乙個困惑點,那個絕對值的比較是什麼東西,根據數學知識,我們可以知道這個意思是k到i的距離小於k到j的距離,而路線是線性的,這就意味著當且僅當k在j的左邊時才成立,不然總會有k i k j,還不理解?看下圖 如果k在k 的位置,那麼k i一定大於k j吧,所以這個題的題意是只要從j往回...

P5774 JSOI2016 病毒感染

題目鏈結 有 n 個小鎮爆發了疫情,其中第 i 個小鎮每天會死 a i 個人,現在從第乙個小鎮出發,每一天可以選擇 求最少死亡人數 n 3000,a i 10 9 可以發現,每個村莊只可能在第一次被經過或第二次被經過時 被 換句話說,在區間 l,r 進行一次往返走 l rightarrow r ri...

B 病毒感染

有一天clccle和rqy走在某個國家的街頭上,機智的rqy卻發現周圍的行人不太對勁,他們嘴裡念念有詞,說著 sqn tql 一邊漫無目的的行走,clccle也發現了這一點,卻驚訝的發覺這種奇怪的病毒會向周圍的城市,最終會感染整個國家,因為網路已經崩潰,所以她們忘記了自己所在的城市,她們唯一知道的是...