Week16 M4

宇宙狗的危机

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

Examples

在这里插入图片描述

题目分析

  1. 总体上采用区间dp的思想,在计算过程中发现需要附加信息以完成计算,在搜索根节点的信息很重要中所以额外存储了根节点的信息
  2. 定义dp[i][j]表示i-j是否能形成一颗满足要求的树,l[i][j]表示i-j形成的子树种i节点可以作为根节点,r[i][j]表示i-j形成的子树j节点可以作为根节点
  3. 状态转移方程
if dp[i+1][j]:
for k from i to j-1:
	如果能i+1-k能形成一棵以k为根的树,k-j可以形成一棵以k为根的子树树且gcd(a[i],a[k])>1:
	dp[i][j] = 1
	l[i][j] = 1
	break;
if dp[i][j-1]:
for k from i to j-1:
	如果能i-k能形成一棵以k为根的树,k-j-1可以形成一棵以k为根的子树树且gcd(a[j],a[k])>1:
	dp[i][j] = 1
	r[i][j] = 1
	break;
for k from i+1 to j-1:
	如果能i-k能形成一棵以k为根的树,k-j可以形成一棵以k为根的子树树:
	dp[i][j] = 1
	break;

完整代码

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 800;
int t, n;
int a[maxn];
int dp[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main()
{
	cin >> t;
	while (t--)
	{
		cin >> n;
		for (int i = 0; i < n; i++)
			cin >> a[i];
		for (int i = 0; i < n; i++)
		{
			dp[i][i] = 1;
			r[i][i] = 1;
			l[i][i] = 1;
		}
		for (int len = 2; len <= n; len++) {
			for (int i = 0; i <= n - len; i++)
			{
				int j = i + len - 1;
				if (dp[i + 1][j]) {
					for (int k = i + 1; k <= j; k++)
					{
						if (r[i + 1][k] && l[k][j] && (gcd(a[i], a[k]) > 1))
						{
							dp[i][j] = 1;
							l[i][j] = 1;
							break;
						}
					}
				}
				if (dp[i][j - 1]) {
					for (int k = i; k < j; k++)
					{
						if (r[i][k] && l[k][j - 1] && (gcd(a[j], a[k]) > 1))
						{
							dp[i][j] = 1;
							r[i][j] = 1;
							break;
						}
					}
				}
				for (int k = i + 1; k < j; k++)
				{
					dp[i][j] = max(dp[i][j], dp[i][k] & dp[k][j] & r[i][k] & l[k][j]);
					if (dp[i][j])
						break;
				}
			}
		}
		if (dp[0][n - 1])
			cout << "Yes" << endl;
		else
			cout << "No" << endl;
		memset(dp, 0, sizeof(dp));
		memset(r, 0, sizeof(r));
		memset(l, 0, sizeof(l));
	}
	return 0;
}

note

感觉这个题对我来说不好想,花了很长时间,最开始的时候意识到信息不够时总想通过增加维数来增加信息,现在意识到可以单独开辟一块位置来存储信息。另外,如何保留有用的信息也是一个难点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值