P8248 简单数列 题解

首先,圈重点:

  1. $1\le n \le 500$
  2. 所有元素在 $1\sim4$ 之间
  3. 任意连续的连续子串不相同
  4. 只要输出一种答案即可

于是我们可以得到的是:

  • 由第一点和第二点可以看出此题可以写搜索解决。
  • 由第三点我们可以得到一种剪枝方式,就是如果目前数字放入后会产生相同的连续的连续子串。
  • 由第四点我们可以发现结束搜索的条件,同时节约时间。

搜索方法:

  1. 如果已输出一种,一直返回至主函数(也可以在输出后直接 exit(0))。
  2. 如果当前要填的位置是 $n + 1$,说明已经填好了 $n$ 个数字且无连续的连续子串相同,此时输出并且标记。
  3. 循环在当前位置填入 $1\sim4$,判断填入后是否有连续的连续子串相同,如果没有,则进入 dfs(step + 1)

分析结束,上代码

#include<cstdio>
using namespace std;
const int N = 500 + 5;
int n, a[N];//a用来存当前的串 
bool flag;//用来标记是否找到合法答案 
bool check(int x)//用来判断a[1~x]是否合法 
{
	for(int i = 1;i * 2 <= x; i++)//因为有两个串对比,i枚举的是子串长度 
	{
		bool flag = 0;
		for(int j = 1;j <= i; j++)//j枚举对第几个数字 
			if(a[x - j + 1] != a[x - i - j + 1])//如果有1个不同的就标1 
			{
				flag = 1;
				break; 
			} 
		if(!flag)//如果全部相同返回0 
			return 0;
	}
	return 1;
}
void dfs(int step)
{
	if(flag)//如果已输出答案,返回 
		return ;
	if(step == n + 1)//如果n个数都已经放入,则输出答案并标1 
	{
		for(int i = 1;i <= n; i++)
			printf ("%d ", a[i]);
		flag = 1;
		return ;
	}
	for(int i = 1;i <= 4; i++)//枚举该位填的数字 
	{
		a[step] = i;
		if (check(step))//填入后判断填此数字后是否合法 
			dfs(step + 1);
		a[step] = 0;//回溯 
	}
	return ;
}
int main()
{
	scanf ("%d", &n);
	dfs(1);
	return 0;
}

完结撒花

如有错误欢迎私信指出

posted @ 2024-02-17 20:53  睡不醒的凪  阅读(17)  评论(0)    收藏  举报