MENU

4.22深搜题解

April 22, 2020 • 题解

一、P1030求先序排列

题目描述

给出一棵二叉树的中序与后序排列。求出它的先序排列。
(约定树结点用不同的大写字母表示,长度≤8)。

输入格式

2行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。

输出格式

1行,表示一棵二叉树的先序。

输入输出样例

输入 #1

BADC
BDCA

输出 #1

ABCD

题解:

题中给出了两个字符串,分别为二叉树的中序和后序排列,在后序排列中可知,后序排列的最后一个值为根节点,因此,我们只需要不停的寻找子节点的后序排列并且输出其最后的那个值就可以得到答案了

比如题中所给的例子:

BADC
BDCA

在第二行中,最后一个为A,所以最终的根节点为A,我们先输出A,然后在第一个字符串中遍历,找到根节点A的位置,

因此,根节点A左边的B就是子节点1的中序排列,根节点有边的DC就是子节点2中的中序排列,我们在第二个字符串中,取出长度等于子节点1的一段B,这一段就是子节点1对应的后序排列

相同的,取出第二个字符串中剩下的字符串DC,这段就是子节点2对应的后续排列

利用刚才分离的子字符串,开始后续的递归搜索,就可以输出前序排列了

本题样例的二叉树:

本题样例的二叉树

AC代码:

/*
 * @Author: Mr.Sen
 * @LastEditTime: 2020-04-22 16:42:08
 * @Website: https://449293786.site
 * @原创代码,版权所有,转载请注明原作者
 */
#include <bits/stdc++.h>
using namespace std;

void dfs(string mid,string after)
{
    int loc;//记录根节点在中序排列的位置
    if (mid.length()==0||after.length()==0) return ;
    cout<<after[after.length()-1];
    for (int i=0;i<mid.length();i++)
        if (mid[i]==after[after.length()-1]) loc=i;
        //在中序排列中寻找根节点的位置
    dfs(mid.substr(0,loc),after.substr(0,loc));
    dfs(mid.substr(loc+1),after.substr(loc,mid.length()-loc-1));
    //递归搜索
}
int main()
{
    string mid,after;
    cin>>mid>>after;
    dfs(mid,after);
    return 0;
}

string的相关内容请看这里


二、P1057传球游戏

题目描述

上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。

游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没有传出去的那个同学就是败者,要给大家表演一个节目。

聪明的小蛮提出一个有趣的问题:有多少种不同的传球方法可以使得从小蛮手里开始传的球,传了m次以后,又回到小蛮手里。两种传球方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有三个同学1号、2号、3号,并假设小蛮为1号,球传了3次回到小蛮手里的方式有1->2->3->1和1->3->2->1,共22种。

输入格式

一行,有两个用空格隔开的整数n,m(3≤n≤30,1≤m*≤30)。

输出格式

11个整数,表示符合题意的方法数。

输入输出样例

输入 #1复制

3 3

输出 #1复制

2

说明/提示

40%的数据满足:3≤n≤30,1≤m≤20

100%的数据满足:3≤n≤30,1≤m≤30

2008普及组第三题

题解

这题我实在不知道怎么剪枝了,所以我直接波纹疾走

打表代码:

/*
 * @Author: Mr.Sen
 * @LastEditTime: 2020-04-22 15:46:17
 * @Website: https://449293786.site
 * @原创代码,版权所有,转载请注明原作者
 */
#include <bits/stdc++.h>
using namespace std;
int note[31][31];
int n,m,loop=0,ans=0;

void dfs(int cur,int loop)
{
    if (loop%n==0&&cur==m)
    {
        ans++;
        return ;
    }
    if (cur==m) return ;
    dfs(cur+1,loop+1);
    dfs(cur+1,loop-1);
}
int main()
{
    for (int i=3;i<=30;i++)
    {
        for (int j=1;j<=30;j++)
        {
            n=i,m=j;
            dfs(0,0);
            printf("%d,",ans);
            ans=0;
        }
    }
    return 0;
}

AC代码:

/*
 * @Author: Mr.Sen
 * @LastEditTime: 2020-04-22 15:55:46
 * @Website: https://449293786.site
 * @原创代码,版权所有,转载请注明原作者
 */
#include <bits/stdc++.h>
using namespace std;
int ans[30][30]={ 0,2,2,6,10,22,42,86,170,342,682,1366,2730,5462,10922,21846,43690,87382,174762,349526,699050,1398102,2796202,5592406,11184810,22369622,44739242,89478486,178956970,357913942,0,2,0,8,0,32,0,128,0,512,0,2048,0,8192,0,32768,0,131072,0,524288,0,2097152,0,8388608,0,33554432,0,134217728,0,536870912,0,2,0,6,2,20,14,70,72,254,330,948,1430,3614,6008,13990,24786,54740,101118,215766,409640,854702,1652090,3396916,6643782,13530350,26667864,53971350,106914242,215492564,0,2,0,6,0,22,0,86,0,342,0,1366,0,5462,0,21846,0,87382,0,349526,0,1398102,0,5592406,0,22369622,0,89478486,0,357913942,0,2,0,6,0,20,2,70,18,252,110,924,572,3434,2730,12902,12376,48926,54264,187036,232562,720062,980674,2789164,4086550,10861060,16878420,42484682,69242082,166823430,0,2,0,6,0,20,0,72,0,272,0,1056,0,4160,0,16512,0,65792,0,262656,0,1049600,0,4196352,0,16781312,0,67117056,0,268451840,0,2,0,6,0,20,0,70,2,252,22,924,156,3432,910,12870,4760,48622,23256,184796,108528,705894,490314,2708204,2163150,10430500,9373652,40313160,40060078,156305070,0,2,0,6,0,20,0,70,0,254,0,948,0,3614,0,13990,0,54740,0,215766,0,854702,0,3396916,0,13530350,0,53971350,0,215492564,0,2,0,6,0,20,0,70,0,252,2,924,26,3432,210,12870,1360,48620,7752,184756,40698,705434,201894,2704204,961400,10401250,4440150,40123152,20030010,155172330,0,2,0,6,0,20,0,70,0,252,0,926,0,3460,0,13110,0,50252,0,194446,0,758100,0,2973350,0,11716252,0,46333566,0,183739940,0,2,0,6,0,20,0,70,0,252,0,924,2,3432,30,12870,272,48620,1938,184756,11970,705432,67298,2704156,354200,10400602,1776060,40116656,8584290,155118390,0,2,0,6,0,20,0,70,0,252,0,924,0,3434,0,12902,0,48926,0,187036,0,720062,0,2789164,0,10861060,0,42484682,0,166823430,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,2,12870,34,48620,342,184756,2660,705432,17710,2704156,106260,10400600,592020,40116600,3121560,155117522,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12872,0,48656,0,185136,0,708512,0,2725408,0,10532160,0,40870080,0,159189120,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,2,48620,38,184756,420,705432,3542,2704156,25300,10400600,161460,40116600,950040,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48622,0,184796,0,705894,0,2708204,0,10430500,0,40313160,0,156305070,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,2,184756,42,705432,506,2704156,4600,10400600,35100,40116600,237510,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184758,0,705476,0,2704708,0,10405800,0,40157550,0,155402532,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,2,705432,46,2704156,600,10400600,5850,40116600,47502,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705434,0,2704204,0,10401250,0,40123152,0,155172330,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,2,2704156,50,10400600,702,40116600,7308,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704158,0,10400652,0,40117356,0,155125640,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704156,2,10400600,54,40116600,812,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704156,0,10400602,0,40116656,0,155118390,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704156,0,10400600,2,40116600,58,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704156,0,10400600,0,40116602,0,155117580,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704156,0,10400600,0,40116600,2,155117520,0,2,0,6,0,20,0,70,0,252,0,924,0,3432,0,12870,0,48620,0,184756,0,705432,0,2704156,0,10400600,0,40116600,0,155117522
};
int main()
{
    int n,m;
    cin>>n>>m;
    cout<<ans[n-3][m-1]<<endl;
    //修正结果,因为是从3开始搜的,所以减2再减1
    return 0;
}

其实本题的标程应该是用DP写的,可是奈何本人没文化,懒得写了,以后有空再补吧……

三、P1433吃奶酪

题目描述

房间里放着 n 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0)点处。

输入格式

第一行一个正整数n

接下来每行 22 个实数,表示第i块奶酪的坐标。

两点之间的距离公式为 sqrt{(x_1-x_2)^2+(y_1-y_2)^2}(x1−x2)2+(y1−y2)2。

输出格式

一个数,表示要跑的最少距离,保留 22 位小数。

输入输出样例

输入 #1

4
1 1
1 -1
-1 1
-1 -1

输出 #1

7.41

说明/提示

1≤n≤15。

题解:

这题普通的深搜加剪枝是过不了的!!!疑似2019年7月~2020年4月之间有数据变动!!!

深搜是有极限的,所以我们这里得引入状态压缩的的思想……但其本质还是深搜

AC代码:

/*
 * @Author: Mr.Sen
 * @LastEditTime: 2020-04-22 19:32:33
 * @Website: https://449293786.site
 * @原创代码,版权所有,转载请注明原作者
 */
#include <bits/stdc++.h>

using namespace std;

int n;
long double a[30][2],lt[30][30],zt[(1<<15)+15][18];
long double cc1,cc2,answ;
int bj[30],i,j;

void dfs(int y,int ww,int x,long double ans){
    if(x==n+1) if(answ==0 || answ>ans) {answ=ans;return;}
    for(int g=1;g<=n;g++)
    {
        if(!bj[g])
        {
            int xb=ww+(1<<(g-1));
            if(zt[xb][g]!=0)
            if(zt[xb][g]<=ans+lt[y][g]) continue;
            bj[g]=1;
            zt[xb][g]=ans+lt[y][g];
            dfs(g,xb,x+1,zt[xb][g]);
            bj[g]=0;
        }
    }
    return;
}

int main(){
    cin>>n;
    a[0][0]=0;a[0][1]=0;
    for(i=1;i<=n;i++)
    {
        scanf("%lf %lf",&a[i][0],&a[i][1]);
        for(j=0;j<i;j++)
        {
            cc1=a[i][0]-a[j][0];
            cc2=a[i][1]-a[j][1];
            lt[j][i]=sqrt(cc1*cc1+cc2*cc2);
            lt[i][j]=lt[j][i];
        }
    }
    dfs(0,0,1,0);
    printf("%.2lf",answ);
    return 0;
}

下面是完全的状态压缩算法:

#include<cstdio>
#include<cmath>
#include<cstring>
typedef double db;
db x[20],y[20],f[20][35000];
template<class T> T min(T a,T b) {return a<b?a:b;}
db dis(int a,int b) {return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));}
int main()
{
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]);
    memset(f,127,sizeof(f));
    for(int s=1;s<=(1<<n)-1;s++)
    for(int i=1;i<=n;i++)
    {
        if((s&(1<<(i-1)))==0) continue;
        if(s==(1<<(i-1))) {f[i][s]=0;continue;}
        for(int j=1;j<=n;j++)
        {
            if((s&(1<<(j-1)))==0||i==j) continue;
            f[i][s]=min(f[i][s],f[j][s-(1<<(i-1))]+dis(i,j));
        }
    }
    db ans=-1;
    for(int i=1;i<=n;i++)
    {
        db s=f[i][(1<<n)-1]+dis(i,0);
        if(ans==-1||ans>s) ans=s;
    }
    printf("%.2lf\n",ans);
    return 0;
}
作者:NorthCity1984
出处:https://grimoire.cn/acm/422-dfs.html
版权:本文《4.22深搜题解》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任