【區間DP】Codeforces#505D 1025D Recovering BST
阿新 • • 發佈:2019-02-06
題意
給n個數,問能否構造出一個相鄰節點不互質的二叉搜尋樹。
題解
JZ太神了,看了一眼就說區間DP。
定義表示接在的右兒子是否可行,表示接在的左兒子是否可行。轉移就用經典區間DP,列舉中的一個作為根。
程式碼
#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;
}