P1063 能量項鏈 區間DP
我原本的dfs的轉移式子就只有將兩邊的單個拎出來,將其余的大基團合并
也就是這兩個情況:

和

但是忽視了類似這種的情況:

也就是說,我沒有討論兩個大基團合并的情況,只討論了單點跟基團合并
后來開始使用區間DP的套路
然而出現了如下這些問題:
先上個AC代碼,其中有死亡處被我用括號括起來了
#include<iostream> #include<cstdio> #define NUM 510 #define int long long #define FOR(a,b,c) for( int a = b;a <= c;a++ ) using namespace std; int n; int a[NUM]; long long dp[NUM][NUM]; signed main(){ cin >> n; FOR( i,1,n ){ cin >> a[i]; a[i+n] = a[i]; } FOR( len,2,n+2 ){ //枚舉區間長度(n+1) FOR( l,1,n*2-len+1 ){ //( 循環條件改了,原來是枚舉到n ) int r = l+len-1; // if( len == 2 ){ //( 刪除掉! ) // dp[l][r] = a[l]*a[r]*a[r+1]; // printf( "區間為%d-%d,dp = %d\n",l,r,dp[l][r] ); // continue; // } FOR( t,l+1,r-1 ){ dp[l][r] = max( dp[l][r],dp[l][t]+dp[t][r]+a[l]*a[t]*a[r] );//(*a[t]*a[r]) } // printf( "區間為%d-%d,dp = %d\n",l,r,dp[l][r] ); } } long long ans = 0; FOR( i,1,n ){ ans = max( ans,dp[i][i+n] );//( [i+n] ) } cout << ans; return 0; }
1. 不要特判長度為$2$,直接讓長度$3$的去作為最小的區間,甚至可以不要長度為2的更新
2. 答案為dp[i][i+n],因為是個環,所以要有$n+1$個數
3. 如2,區間長度也要是$n+1$
4. 枚舉起點要枚舉到$n*2-len+1$,因為不同的區間長度,不能都是枚舉到$n$是吧(xjj)
5. 理解問題了就是,轉移方程應該是由
轉移得到

浙公網安備 33010602011771號