1. 程式人生 > 其它 >Treats for the Cows G/S——區間dp

Treats for the Cows G/S——區間dp

P2858 [USACO06FEB]Treats for the Cows G/S - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)

不得不說,這道題有一點顛覆我的思維方式。

剛開始,我覺得這道題和合唱隊那道題一樣(其實就是差不多),但是我就是固定思維想用個三維陣列,分別求出在左邊和在右邊的最大值,最後進行比較得出答案。笨蛋!人家又不是隻能一直從一邊出來,正確的思考應該是從左出來點,從右出來點。

 

狀態表示:區間[i,j]的最大價值。

狀態計算:可以從左端點出來,f[i+1,j]+v[i]*(n-len+1)    //n-len+1怎麼來的? 後面有

     可以從右端點出來,f[i,j-1]+v[j]*(n-len+1)

      f[i,j]就是上述兩種表示式求max

最終求得是f[1][n]

初始化:因為方程表示的是區間[i,j]的最大價值,所以f[i,i]應該初始化為v[i]*n,n是最大的天數,這樣才滿足最大價值。

    因此狀態計算中的(n-len+1)就是對應的天數。emmmm,這也就是顛覆我的地方。這個天數表示的意思就是它是倒著賣的,最後一天賣的是f[i,i],第一天賣的是f[1,n],而這樣倒著賣的原因就是初始化的時候根據方程定義,把f[i,i]初始化為最大天數才賣掉它,這樣才符合方程定義。

 

 1 #include <bits/stdc++.h>
 2 using namespace
std; 3 const int N=2e3+100; 4 typedef long long ll; 5 ll f[N][N],v[N]; 6 7 8 int main() 9 { 10 int n;scanf("%d",&n); 11 for(int i=1;i<=n;i++)scanf("%d",&v[i]); 12 13 for(int len=1;len<=n;len++) 14 { 15 for(int i=1;i+len-1<=n;i++) 16 { 17 int
j=i+len-1; 18 if(i==j) 19 { 20 f[i][j]=v[i]*n; 21 continue; 22 } 23 f[i][j]=max(f[i][j-1]+v[j]*(n-len+1),f[i+1][j]+v[i]*(n-len+1)); 24 } 25 } 26 printf("%lld\n",f[1][n]); 27 28 29 return 0; 30 }
View Code