1. 程式人生 > >【動態規劃】bzoj1575: [Usaco2009 Jan]氣象牛Baric

【動態規劃】bzoj1575: [Usaco2009 Jan]氣象牛Baric

return best 之間 sizeof 有一點 tput 處理 getc limit

預處理普通動態規劃;慶祝1A三連

Description

為了研究農場的氣候,Betsy幫助農夫John做了N(1 <= N <= 100)次氣壓測量並按順序記錄了結果M_1...M_N(1 <= M_i <= 1,000,000). Betsy想找出一部分測量結果來總結整天的氣壓分布. 她想用K(1 <= K <= N)個數s_j (1 <= s_1 < s_2 < ... < s_K <= N)來概括所有測量結果. 她想限制如下的誤差: 對於任何測量結果子集,每一個非此子集中的結果都會產生誤差.總誤差是所有測量結果的誤差之和.更明確第說, 對於每一個和所有s_j都不同的i: * 如果 i 小於 s_1, 誤差是: 2 * | M_i - M_(s_1) | * 如果i在s_j和s_(j+1)之間,誤差是: | 2 * M_i - Sum(s_j, s_(j+1)) | 註:Sum(x, y) = M_x + M_y; (M_x 和 M_y 之和) * 如果i大於s_K,誤差為: 2 * | M_i - M_(s_K) | Besty給了最大允許的誤差E (1 <= E <= 1,000,000),找出最小的一部分結果史得誤差最多為E.

Input

* 第一行: 兩個空格分離的數: N 和 E

* 第2..N+1行: 第i+1行包含一次測量記錄:M_i

Output

* 第一行: 兩個空格分開的數: 最少能達到誤差小於等於E的測量數目和使用那個測量數目能達到的最小誤差.

Sample Input

4 20
10
3
20
40

輸入解釋:

Bessie做了4次記錄,分別為10,3,20,和40.最大允許誤差是20.

Sample Output

2 17

HINT

選擇第二和第四次測量結果能達到最小誤差17. 第一次結果的誤差是2*|10-3| = 14; 第三次結果的誤差是|2*20 - (3+40)|=3.


題目分析

算是一道有一點復雜的簡單動態規劃。

題目的子結構稍微需要轉化一下,因為不同邊界的加權是不一樣的,然後就可以預處理亂搞了。

 1 #include<bits/stdc++.h>
 2 const int maxn = 103;
 3 
 4 int n,m[maxn],limit;
 5 int f[maxn][maxn][maxn],s[maxn][maxn],g[maxn],h[maxn][maxn];
 6 
 7 int read()
 8 {
 9     char ch = getchar();
10     int num = 0
; 11 bool fl = 0; 12 for (; !isdigit(ch); ch = getchar()) 13 if (ch==-) fl = 1; 14 for (; isdigit(ch); ch = getchar()) 15 num = (num<<1)+(num<<3)+ch-48; 16 if (fl) num = -num; 17 return num; 18 } 19 int abs(int x){return x>0?x:-x;} 20 int main() 21 { 22 memset(f, 0x3f3f3f3f, sizeof f); 23 memset(g, 0x3f3f3f3f, sizeof g); 24 n = read(), limit = read(); 25 for (int i=1; i<=n; i++) m[i] = read(); 26 for (int i=0; i<=n; i++) 27 { 28 if (i) 29 for (int j=i+1; j<=n; j++) 30 for (int k=i+1; k<j; k++) 31 s[i][j] += abs(2*m[k]-m[i]-m[j]); 32 else 33 for (int j=1; j<=n; j++) 34 for (int k=1; k<j; k++) 35 s[i][j] += 2*abs(m[j]-m[k]); 36 } //checked 37 for (int i=1; i<=n; i++) 38 for (int j=i+1; j<=n; j++) 39 for (int k=i+1; k<j; k++) 40 h[i][j] += 2*abs(m[i]-m[k]); 41 f[0][0][0] = 0; 42 for (int i=0; i<n; i++) 43 for (int j=0; j<=i; j++) 44 for (int k=j; k<=i; k++) 45 { 46 int tt = j?(2*abs(m[i+1]-m[k])):0; 47 f[i+1][j+1][i+1] = std::min(f[i][j][k]+s[k][i+1]-h[k][i+1], f[i+1][j+1][i+1]); 48 f[i+1][j][k] = std::min(f[i][j][k]+tt, f[i+1][j][k]); 49 } 50 for (int i=1; i<=n; i++) 51 { 52 for (int k=i; k<=n; k++) 53 g[i] = std::min(g[i], f[n][i][k]); 54 if (g[i] < limit){ 55 printf("%d %d\n",i,g[i]); 56 return 0; 57 } 58 } 59 return 0; 60 }

END

【動態規劃】bzoj1575: [Usaco2009 Jan]氣象牛Baric