習題:Array Shrinking(DP)
阿新 • • 發佈:2020-07-29
題目
思路
考慮到一個區間如果能縮成一個點,那麼這個點的值一定是確定的
所以我們設\(dp[l][r]\)為區間\(l,r\)最終縮成的點的值
如果不能縮成一個點,那麼\(dp[l][r]=0\)
\(dp[l][r]\)的轉移列舉一個分界點即可
之後就是一個劃分區間的問題
按照套路,設\(f[i]\)為前i個數構造的陣列剩餘的最小值
\(f[i]=min\{f[j]+1[dp[j+1][i]!=0]\}\)
程式碼
#include<iostream> #include<cstring> using namespace std; int n; int a[505]; int f[505][505]; /* 區間l~r縮成一個點之後的數是多少 如果不能縮成一個點,值為0 */ int dp[505];//前i個數的最小長度 int dfs1(int l,int r) { if(f[l][r]!=-1) return f[l][r]; for(int i=l;i<r;i++) { if(dfs1(l,i)==dfs1(i+1,r)&&dfs1(l,i)!=0) { f[l][r]=f[l][i]+1; return f[l][r]; } } f[l][r]=0; return 0; } int main() { ios::sync_with_stdio(false); memset(f,-1,sizeof(f)); cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; f[i][i]=a[i]; } dfs1(1,n); for(int i=1;i<=n;i++) { dp[i]=i; for(int j=0;j<i;j++) if(f[j+1][i]!=0) dp[i]=min(dp[i],dp[j]+1); } cout<<dp[n]; return 0; }