2023年蓝桥杯省赛 接龙数列 知识点:dfs穷举+dp优化

95 阅读2分钟

1.接龙数列 - 蓝桥云课 (lanqiao.cn)

视频解析:[蓝桥杯]真题讲解:接龙序列(暴力、线性DP)_哔哩哔哩_bilibili

题意

题目说了让我们最少删除多少个数保证序列为接龙序列。

我们倒推:最多保留多少个数,保证序列为接龙序列。

假设最多保留了res位数,那么就是最少要删除n-res位数,才可以保证序列为接龙序列。

思想

对于每一个数我们都有选和不选两种选择,因此我们总共有2n 2^{n}种选择。 image.png 我们可以将其画为一个树状图:

image.png 如果我们要选当前数,那么我们就要判断一下当前数是否合法,即当前数的最后一位数是否和下一个数的第一位数相同。如果合法,我们才能选择。

复杂度解析

2202^{20}次方是1024101024^{10}就是1e9多了,因此如果用dfs只能过20%的数据 image.png

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
#define int long long
int a[N];
int n,ans;

int get_first(int x)
{
	int res = 0;
	while (x)
	{
		res = x % 10;
		x /= 10;
	}
	return res;
}


int get_last(int x)
{
	int res = x % 10;
	return res;
}

void dfs(int u,int cnt,int last)
{
	if (u >= n)  //i从0开始的,当i为n的时候说明所有的元素都处理完,我们选择一个保留最多的方案,那就是删除最少的方案
	{
		ans = max(ans,cnt);
		return;
	}

	//选
	if (last == -1 || get_last(last) == get_first(a[u]))  //第一个数没选的时候last初始化为-1,表示可选可不选
	{
		dfs(u + 1, cnt + 1, a[u]);  //第u位选择,考虑下一位 方案数+1 last更新为a[u]
	}

	dfs(u+1,cnt,last); //第u位不选 方案数不变 last不变
}
signed main()
{
	cin.tie(nullptr)->sync_with_stdio(false);
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}

	dfs(0,0,-1);

	cout << n - ans << endl;
	return  0;
}

image.png