Treats for the Cows G/S——區間dp
阿新 • • 發佈:2022-04-04
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 namespaceView Codestd; 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 intj=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 }