洛谷 P3146 248 題解
阿新 • • 發佈:2018-08-23
為什麽 div ace 更新 quest break 超出 def nbsp
https://www.luogu.org/problemnew/show/P3146
區間dp,這次設計的狀態和一般的有一定的差異。
這次我們定義$dp[i][j]$表示$[i,j]$的可以合並出來最大取值,而不是合並區間$[i,j]$的最大取值。
同樣的我們枚舉區間長度,枚舉左端點,求出右端點。
枚舉$i$到$j$之間的每一個分割點,判斷兩點之間是否可以合並,取價值更高的答案。
$$dp[i][j]=max(dp[i][j],dp[i][k]+1) [dp[i][k]==dp[i][k+1]$$
Question 1:其他的點不需要更新,為什麽?
這就要看我們設計的狀態了,我們定義的是區間[i,j]可以合並出來的最大值,答案唯一,當然不能用其位置的更新了。
Question 2:答案是什麽?
註意這裏的答案不一定是$dp[1][n]$,你想當我們計算區間[1,n]時所有的$dp[i][k]!=dp[k+1][j]$那麽區間$[1,n]$的答案為$0$,答案在之前已經得出,所以我們在過程中記錄一下就好了。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <queue> #include <map> usingnamespace std; #define LL long long #define mod int(1e9+7) int n,a[250],dp[250][250],ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); dp[i][i]=a[i]; //初始化dp數組 } for(int len=2;len<=n;len++) { for(inti=1;i<=n;i++) { int j=i+len-1; if(j>n)break; //超出長度限制 for(int s=i;s<j;s++) { if(dp[i][s]==dp[s+1][j])dp[i][j]=max(dp[i][j],dp[i][s]+1); } ans=max(dp[i][j],ans); //記錄答案 } } printf("%d",ans); }
洛谷 P3146 248 題解