M4--C - 宇宙狗的危机

题目

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

思路

二叉搜索树

它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二叉搜索树要求为二叉,且为搜索树

解题

应用动态规划
f[i][j]记录i到j能不能构造成这样得一个二叉搜索树。
记录每两个数之间的gcd是不是大于1
l[i][j]表示以j为跟,i,j为左子树的合法的树。
r[i][j]则是表示以i为根,i,j为右子树的合法的树。
依次枚举区间长度len,和数组中该长度的区间,并在该长度的区间中枚举根节点,转移条件为
l[q][root] && r[root][z],同时在gcd2[q - 1][root],gcd2[root][z + 1]为1时分别更新r[q-1][z]和l[q][z+1]

代码

#include<iostream>
#include<string.h>
using namespace std;
int node[710];
int gcd(int a,int b){
    
    return b == 0 ? a : gcd(b,a%b);}
bool f[710][710];
bool gcd2[710][710];
bool l[710][710],r[710][710];
int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		memset(f,0,sizeof(f));
		memset(gcd2, 0, sizeof(gcd2));
		memset(l, 0, sizeof(l));
		memset(r, 0, sizeof(r));		
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
    
    
			cin>>node[i];
			l[i][i]=1;
			r[i][i]=1;			
		}
		for (int i = 1; i <= n; i++)
		{
    
    
			for (int j = 1; j <= n; j++)
			{
    
    
				if (i!=j && gcd(node[i], node[j]) > 1)
				{
    
    
					gcd2[i][j] = true;	
				}
			}
		}
		for (int len = 0; len < n; len++)
		{
    
    
			for (int q = 1; q <= n-len; q++)
			{
    
    
				int z = q + len;
				for (int root = q; root <= z; root++)
					if (l[q][root] && r[root][z])
					{
    
    
						f[q][z] = 1;
						if (gcd2[q - 1][root]) 
							r[q - 1][z] = 1;
						if (gcd2[root][z + 1]) 
							l[q][z + 1] = 1;
					}
			}
		}
		if (f[1][n]) 
			cout << "Yes" << endl;
		else 
			cout << "No" << endl;		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/alicemh/article/details/106604486