Codeforces Round #505 D. Recovering BST(區間dp)

題目鏈接:http://codeforces.com/contest/1025/problem/D

題目大意:已知一棵二叉搜索樹的n個結點的權值,同時知道只有在兩個權值gcd不爲1的點之間纔會有邊。現在給出這n個結點的權值(按升序給出),問你這n個結點是否能組成一棵二叉搜索樹。

題目思路:一開始沒往dp方面想,就傻傻地想着用特判的方法去處理一些特殊情況,寫到後面才發現情況太多了根本無法處理。後面看了大神的博客才懂了這題得用區間dp來寫。

我們設dp[i][j][0]表示第 i 個結點到第 j 個結點作爲某一棵二叉搜索樹的左子樹是否可行,dp[i][j][1]表示作爲右子樹是否可行。

接下來就可以進行狀態轉移,我們分別枚舉二叉搜索樹的大小,起點和終點,以及根節點的位置。

轉移完之後再枚舉最後的根節點是哪個即可。

具體實現看代碼:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
typedef vector<int> VI;
const int inf = 0x3f3f3f3f;
const int MX = 700 + 7;

int n;
int p[MX];
bool dp[MX][MX][2], g[MX][MX], flag;
ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a % b);
}

int main() {
	//FIN;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (i == j) continue;
			g[i][j] = gcd(p[i], p[j]) > 1;
		}
	}
	for (int l = 1; l <= n; l++) {
		for (int i = 1, j; i + l - 1 <= n; i++) {
			j = i + l - 1;
			for (int k = i; k <= j; k++) {

				flag = 1;
				if (k == i) flag &= 1;
				else flag &= dp[i][k - 1][0];

				if (k == j) flag &= 1;
				else flag &= dp[k + 1][j][1];

				if (flag) {
					dp[i][j][0] |= g[k][j + 1];
					dp[i][j][1] |= g[k][i - 1];
				}
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		flag = 1;

		if (i == 1) flag &= 1;
		else flag &= dp[1][i - 1][0];

		if (i == n) flag &= 1;
		else flag &= dp[i + 1][n][1];
		if (flag) {
			puts("Yes");
			return 0;
		}
	}
	puts("No");
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章