dfs+剪枝(暑假集训第三周周测E)

来源:互联网 发布:淘宝卖家信誉帐号 编辑:程序博客网 时间:2024/05/17 00:51

这里写图片描述
☝题目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这个值不是整体变量,而是作为一个递归的量,一直在变化!

真神奇!

原创粉丝点击