1. 程式人生 > >【區間DP】Codeforces#505D 1025D Recovering BST

【區間DP】Codeforces#505D 1025D Recovering BST

題意

給n個數,問能否構造出一個相鄰節點不互質的二叉搜尋樹。

題解

JZ太神了,看了一眼就說區間DP。

定義lft[i][j]表示[i,j]接在i1的右兒子是否可行,rgt[i][j]表示[i,j]接在j+1的左兒子是否可行。轉移就用經典區間DP,列舉[i,j]中的一個作為根。

程式碼

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=706
; int n,a[maxn]; bool g[maxn][maxn],lft[maxn][maxn],rgt[maxn][maxn]; int gcd(int x,int y){return !y?x:gcd(y,x%y);} int main(){ freopen("D.in","r",stdin);freopen("D.out","w",stdout); scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<n;i++) for(int j=i+1
;j<=n;j++) if(gcd(a[i],a[j])>1)g[i][j]=g[j][i]=1; for(int i=1;i<=n;i++)g[0][i]=g[i][0]=g[i][n+1]=g[n+1][i]=1; for(int i=n;i>=1;i--) for(int j=i;j<=n;j++) for(int k=i;k<=j;k++) if((k==i||rgt[i][k-1])&&(k==j||lft[k+1][j]))lft[i][j]|=g[k][i-1],rgt[i][j]|=g[k][j+1
]; for(int i=1;i<=n;i++) if((i==1||rgt[1][i-1])&&(i==n||lft[i+1][n]))return puts("Yes"),0; return puts("No"),0; }