1. 程式人生 > >CF D. Recovering BST (區間DP)

CF D. Recovering BST (區間DP)

sed const amp \n close style 兩個 span bsp

題意:給你n個節點,每個節點有一個權值,兩個點可以連邊當且僅當這兩個點的gcd>1,問你這n個點能否構成一個二叉搜索樹(每個節點最多有兩個兒子,且左兒子小於右兒子),輸入為遞增順序。

分析:

若以第K個節點,用L[i][k] ,表示是否可以延伸到i點,R[k][j]表示是否可以延伸到J點,那區間【L,R]怎樣才是合法的呢?很顯然只有L[i][k] && R[k][j] ==1,時這個區間才是合法的,那只要在【1,n】,這個區間裏找到存在點K ,那就是YES ,否則NO;

技術分享圖片
#include<stdio.h>
const int maxn = 701;
int gcd(int
a , int b) { if(b==0) return a; return gcd(b,a%b); } int a[maxn],L[maxn][maxn],R[maxn][maxn],val[maxn][maxn]; int main( ) { int n ; scanf("%d",&n) ; for(int i=1 ; i<=n ; i++) { scanf("%d",&a[i]) ; L[i][i]=R[i][i]=1; } for(int i=1 ; i<n ; i++)
for(int j=i+1 ; j<=n ; j++) { if(gcd(a[i],a[j])>1) { val[i][j]=val[j][i]=1; } else { val[i][j]=val[j][i]=0; } } for(int l=n ; l>=1 ; l--) { for(int r=l ; r<=n ; r++) { for(int
k=l ; k<=r ; k++) { if(L[l][k] && R[k][r]) { if(l==1&&r==n) { printf("Yes\n"); return 0; } if(val[k][l-1]) R[l-1][r]=1; if(val[k][r+1]) L[l][r+1]=1; } } } } puts("No"); return 0 ; }
View Code

CF D. Recovering BST (區間DP)