☝题目http://101.200.220.237/contest/50/problem/295/
dfs题目,但是感觉上就可能会超时。所以加了两个很巧妙的剪枝优化。
嘤嘤嘤,代码过会儿补上,现在有点心累,不想动。
好的,一会儿以后就是一天之后,我写完了代码!
#include<iostream>
using namespace std;
int n, s;//奇异数列的长度和奇异数列的和
int pr[30];
//int sum = 0;
int flag;
void dfs(int step,int num,int sum)
{
pr[step] = num;
sum += num;
if (step == n&&sum == s)
{
flag = 1;
int i;
for (i = 1; i <= n; i++)
cout << pr[i] << " ";
cout << endl;
return;
}
int s1 = (num + 1 + num + n - step)*(n - step) / 2;//剪枝2
int s2 = (num - 1 + num - n + step)*(n - step) / 2;//同为剪枝2
if (sum + s1<s || sum + s2>s)
return;
dfs(step + 1, num - 1,sum);
dfs(step + 1, num + 1,sum);
}
int main()
{
while (cin >> n >> s)
{
memset(pr, 0, sizeof(pr));
flag = 0;
if ((n / 2) % 2 == 0 && s % 2 == 1)
{
cout << "Impossible!\n";
continue;
}//剪枝1
if ((n / 2) % 2 == 1 && s % 2 == 0)
{
cout << "Impossible!\n";
continue;
}//同为剪枝1
dfs(1, 0,0);
flag ? cout << "" : cout << "Impossible!\n";
}
return 0;
}
好的,现在我们来把程序跑一下,最近我迷上了脑动跑程序,感觉跑完一遍就会清晰一些,但是有一个blog主说像dfs、递归这种的局部分析比较好,总体跑就容易把自己绕进去,那我也不知道了。
假设我们输入的是4,0。
输出的应该是:0 -1 0 1, 0 1 0 -1。
进入程序之后dfs(1,0,0),然后进入dfs(2,-1,0),sum此时变成-1,进入dfs(3,-2,-1),在s1的剪枝中被return,进入dfs(3,0,-1),此时sum为-1,然后进入dfs(4,-1,-1),此时sum=-2,被return掉,进入dfs(4,1,-1),sum=0,符合结果输出一组合适的答案,进入dfs(2,1,0),然后sum=1,dfs(3,0,1),sum=1,进入dfs(4,-1,1),sum=0,输出,进入dfs(4,1,1),sum=2,return掉,进入dfs(3,2,1),sum=3,return掉,结束。
下面看一下dfs的整体流程,先是赋值,然后判断,先判断是否符合输出结果的要求,此时可以输出结果,然后进入是否超出条件的判断,然后进入递归。
最重要的就是找准dfs的参数的个数和意义,其次就是各种判断的条件。
在这道题中,sum这个值不是整体变量,而是作为一个递归的量,一直在变化!
真神奇!