首先,圈重点:
- $1\le n \le 500$
- 所有元素在 $1\sim4$ 之间
- 任意连续的连续子串不相同
- 只要输出一种答案即可
于是我们可以得到的是:
- 由第一点和第二点可以看出此题可以写搜索解决。
- 由第三点我们可以得到一种剪枝方式,就是如果目前数字放入后会产生相同的连续的连续子串。
- 由第四点我们可以发现结束搜索的条件,同时节约时间。
搜索方法:
- 如果已输出一种,一直返回至主函数(也可以在输出后直接
exit(0)
)。 - 如果当前要填的位置是 $n + 1$,说明已经填好了 $n$ 个数字且无连续的连续子串相同,此时输出并且标记。
- 循环在当前位置填入 $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;
}
完结撒花
如有错误欢迎私信指出
标签:子串,输出,P8248,数列,相同,int,题解,连续 From: https://www.cnblogs.com/Assassins-Creed/p/18018391