交替调用DFS

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 509;
int a[N];
int f1[N],f2[N];
int n;
int dfs1(int u);
int dfs2(int u);

int main()
{
    cin >> n;
    for(int i=1; i<=n; i++) cin >> a[i];
    int ans = 0;
    for(int i=1; i<=n; i++)
    {
        ans = max(dfs1(i),max(dfs2(i),ans));
    }
    cout<<ans<<"\n";
    return 0;
}
int dfs1(int u)
{
    if(f1[u]) return f1[u];
    f1[u] = 1;
    for(int i=u+1; i<=n; i++)
    {
        if(a[i] > a[u])
        {
            f1[u] = max(f1[u],dfs2(i) + 1);
        }
    }
    return f1[u];
}
int dfs2(int u)
{
    if(f2[u]) return f2[u];
    f2[u] = 1;
    for(int i=u+1; i<=n; i++)
    {
        if(a[i] < a[u])
        {
            f2[u] = max(f2[u],dfs1(i) + 1);
        }
    }
    return f2[u];
}

DFS对于Size与MAX,MIN:

#include<iostream>
#include<cstring>
using namespace std;
const int N = 2e5+9;
int e[N],ne[N],w[N],h[N],idx;
bool st[N];
int root,n,k;
int Size[N],MAX[N],MIN[N];
void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
int dfs(int u)
{
    st[u] = true;
    Size[u] = 1;
    MAX[u] = w[u],MIN[u] = w[u];
    for(int i=h[u]; i!=-1; i=ne[i])
    {
        int j = e[i];
        if(!st[j])
        {	//    [j]		[u]; ??????
          	//deep[u] = deep[j] + 1; 先统计再次递归!
          	//自上而下还是自下而上!
            dfs(j);
            Size[u] += Size[j];  
            MAX[u] = max(MAX[u],MAX[j]);
            MIN[u] = min(MIN[u],MIN[j]);
        }
    }
    return Size[u];
}
int main()
{
    int _;
    scanf("%d",&_);
    while(_--)
    {
        idx = 0;
        memset(st,false,sizeof(st));
        memset(h,-1,sizeof(h));
        memset(Size,0,sizeof(Size));
        memset(MAX,0,sizeof(MAX));
        memset(MIN,0x3f,sizeof(MIN));
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++) scanf("%d",&w[i]);
        for(int i=1; i<n; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b),add(b,a);
        }
        scanf("%d",&root);
        dfs(root);
        int x = -1,ans = 0;
        for(int i=1; i<=n; i++)
        {
            if(Size[i] <= k && MAX[i] - MIN[i] > x)
            {
                x = MAX[i] - MIN[i];
                ans = i;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

状压枚举+BFS

E - 小红的rpg游戏 对标cf 1600 分!
https://ac.nowcoder.com/acm/contest/11218/E
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int N = 109;
const int dx[] = {1,-1,0,0};
const int dy[] = {0,0,1,-1};
char s[N][N];
int vis[N][N];
int n,m,h;
pair<int,int> g[N];
struct node
{
    int x,y,step;
};
struct mon
{
    int x,y,blood;
};
vector<mon> ve;
bool have(int x,int y)
{
    for(int i=0; i<ve.size(); i++)
    {
        if(g[i].first == x && g[i].second == y) return true;
    }
    return false;
}
int bfs()
{
    memset(vis,0,sizeof vis);
    queue<node> qu;
    qu.push({1,1,0});
    vis[1][1] = 1;
    while(!qu.empty())
    {
        auto t = qu.front();
        qu.pop();
        if(t.x == n && t.y == m)
        {
            return t.step;
        }
        for(int i=0; i<4; i++)
        {
            int xx = t.x + dx[i];
            int yy = t.y + dy[i];
            if(xx <= n && xx >= 1 && yy <= m && yy >= 1)
            {
                if(!vis[xx][yy] && (s[xx][yy] == '.'|| have(xx,yy)))
                {
                    vis[xx][yy] = 1;
                    qu.push({xx,yy,t.step+1});
                }
            }
        }
    }
    return -1;
}
int main()
{
    cin >> n >> m >> h;
    for(int i=1; i<=n; i++)
    {
        cin >> s[i] + 1;
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++) if(isdigit(s[i][j])) ve.push_back({i,j,s[i][j] - '0'});
    }
    int ans = 1e9+7;
    for(int i=0; i< 1<<ve.size(); i++)
    {
        memset(g,0,sizeof(g));
        int sum  = 0;
        for(int j=0; j< ve.size(); j++)
        {
            if(1 << j & i)
            {
                g[j].first = ve[j].x,g[j].second = ve[j].y;
                sum += ve[j].blood;
            }
        }
        if(sum >= h) continue;
        int t = bfs();
        if(t != -1) ans = min(ans,t);
    }
    if(ans == 1e9+7) printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

洛谷:P2802 回家
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N = 209;
int n,m;
int mp[N][N],vis[N][N];
int ans;
const int dx[] = {1,-1,0,0};
const int dy[] = {0,0,1,-1};
struct node
{
    int x,y,step,blood;
};
queue<node> qu;
void bfs()
{
    while(!qu.empty())
    {
        auto t = qu.front();
        if(mp[t.x][t.y] == 3 && t.blood > 0)
        {
            ans = t.step;
            break;
        }
        vis[t.x][t.y] = max(vis[t.x][t.y],t.blood);
        qu.pop();
        for(int i=0; i<4; i++)
        {
            int xx = t.x + dx[i];
            int yy = t.y + dy[i];
            if(mp[xx][yy] != 0)
            {
                if(vis[t.x][t.y] > vis[xx][yy] && t.blood > 1)
                {
                    if(mp[xx][yy] == 4) qu.push({xx,yy,t.step+1,6});
                    else qu.push({xx,yy,t.step+1,t.blood - 1});
                }
            }
        }
    }
}
int main()
{
    ios_base :: sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m;
    for(int i=1; i<=n ; i++)
    {
        for(int j=1; j<=m; j++)
        {
            cin >> mp[i][j];
            if(mp[i][j] == 2) qu.push({i,j,0,6}),vis[i][j] = 6;
        }
    }
    ans = -1;
    bfs();
    cout<<ans<<"\n";
    return 0;
}


数据已经加强过了,DFS过不去的!
//可行性剪枝与最优性剪枝!
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 109;
const int dx[] = {1,-1,0,0};
const int dy[] = {0,0,1,-1};
char s[N][N];
int vis[N][N];
int n,m,h;
int ans,f;

void dfs(int x,int y,int h,int step)
{
    if(step > ans && f == 1) return;
    if(x == n && y == m)
    {
        ans = min(ans,step);
        f = 1;
        return;
    }
    vis[x][y] = 1;
    for(int i=0; i<4; i++)
    {
        int xx = x + dx[i];
        int yy = y + dy[i];
        if(xx >= 1 && xx <= n && yy >= 1 && yy <= m)
        {
            if(!vis[xx][yy] && s[xx][yy] != '*')
            {
                if(s[xx][yy] == '.')
                {
                    dfs(xx,yy,h,step+1);
                }
                else if(isdigit(s[xx][yy]))
                {
                    int t = s[xx][yy] - '0';
                    if(h - t > 0)
                    {
                        dfs(xx,yy,h - (s[xx][yy] - '0'),step+1);
                    }
                }
            }
        }
    }
    vis[x][y] = 0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&h);
    for(int i=1; i<=n; i++) scanf("%s",s[i] + 1);
    ans = 1e9;
    f = 0;
    dfs(1,1,h,0);
    if(f) printf("%d\n",ans);
    else printf("-1\n");
    return 0;
}

搜索与剪枝

//记忆化搜索Fi
#include<iostream>
#include<string.h>
using namespace std;
const int N = 1e3+9;
typedef long long ll;
ll Fi[N],dp[N];
long long fi(int n)
{
    if(n == 1 || n == 2) return 1;
    if(Fi[n]) return Fi[n];
  	Fi[n] = fi(n-1) + fi(n-2);
 	return Fi[n];
    //return Fi[n] = fi(n-1) + fi(n-2); 可以直接这样写!
}
int main()
{
    int n;
    cin >> n;
    dp[1] = 1,dp[2] = 1;
    for(int i=3; i<=n; i++) dp[i] = dp[i-1] + dp[i-2];
    cout<<"dp = "<<dp[n]<<endl;
    cout<<"记忆化搜索为 = "<<fi(n)<<endl;
    return 0;
}

记忆化搜索实战! 及两种写法!

洛谷P1434 [SHOI2002]滑雪

//记忆化搜索时f[N],可以初始化为-1,排除答案为0时候的干扰!
//由于递减肯定不会搜到重复点,不需要标记数组!
#include<iostream>
#include<cstring>
using namespace std;
const int N = 309;
int a[N][N],f[N][N];
int n,m;
const int dx[] = {-1,0,0,1};
const int dy[] = {0,1,-1,0};
int ans;
int dfs(int x,int y)
{
    int nowx,nowy;
    if(f[x][y]) return f[x][y];
    f[x][y] = 1;
    for(int i=0; i<4; i++)
    {
        nowx = x + dx[i];
        nowy = y + dy[i];
        if(nowx>=1 && nowx <=n && nowy >=1 && nowy <=m && a[nowx][nowy] < a[x][y])
        {
            f[x][y] = max(f[x][y],dfs(nowx,nowy)+1); //f[x][y] 维护最大值!
          	//dfs(nowx,nowy);
			//f[x][y] = max(f[x][y],f[nowx][nowy]+1); //也可以这样写!
        }
    }
    return f[x][y]; //返回值给上一层用;
}
int main()
{
    ios_base :: sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    cin >> n >> m;
    ans = 1;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++) cin >> a[i][j];
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            ans = max(ans,dfs(i,j));
        }
    }
    cout<<ans<<endl;
    return 0;
}

洛谷P4017 最大食物链计数;

1 无回溯条件!
#include<iostream>
#include<cstring>
using namespace std;
const int N =  3e6+9;
const int mod = 80112002;
int idx,e[N],ne[N],h[N];
int in[N],f[N];
void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
int n,m;
int dfs(int u)
{
    if(f[u]) return f[u];
    f[u] = 1; //由于无回溯条件所以f[u]置为1;
    int sum = 0;
    for(int i=h[u]; i!=-1; i=ne[i])
    {
        int j = e[i];
        sum = (sum + dfs(j)) % mod;
        f[u] = sum;
    }
    return f[u];
}
int main()
{
    ios_base :: sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    memset(h,-1,sizeof h);
    cin >> n >> m;
    for(int i=1; i<=m; i++)
    {
        int a,b;
        cin >> a >> b;
        add(a,b);
        in[b]++;
    }
    int ans = 0;
    for(int i=1; i<=n; i++)
    {
        if(in[i] == 0) ans = (ans + dfs(i))%mod;
    }
    cout<<ans<<endl;
    return 0;
}

2 有回溯条件!
#include<iostream>
#include<cstring>
using namespace std;
const int mod = 80112002;
const int N = 3e6+9;
int ne[N],e[N],h[N],idx;
int n,m;
int f[N];
int in[N],out[N];
void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
int dfs(int u)
{
    if(out[u] == 0) return 1;
    int sum = 0;
    if(f[u]) return f[u];
    for(int i=h[u]; i!=-1; i=ne[i])
    {
        int j = e[i];
        sum = (sum + dfs(j))%mod;
    }
    f[u] = sum % mod;
    return f[u];
}
int main()
{
    int ans = 0;
    memset(h,-1,sizeof h);
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        b[in]++;
        out[a]++;
    }
    for(int i=1; i<=n; i++)
    {
        if(!in[i])
        {
            ans = (ans + dfs(i)) % mod;
        }
    }
    printf("%d\n",ans);
    return 0;
}

acwing 2716. 食物链

//注意单个点不算食物链!
#include<iostream>
#include<cstring>
using namespace std;
const int N = 3e6+9;
int ne[N],e[N],h[N],idx;
int n,m;
int f[N];
int in[N],out[N];
void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
int dfs(int u)
{
    if(out[u] == 0) return 1;
    int sum = 0;
    if(f[u]) return f[u];
    for(int i=h[u]; i!=-1; i=ne[i])
    {
        int j = e[i];
        sum = sum + dfs(j);
    }
    f[u] = sum;
    return sum;
	//int dfs(int u) //也可以这样写
	//{
	//    if(out[u] == 0) return 1;
	//    if(f[u]) return f[u];
	//    for(int i=h[u]; i!=-1; i=ne[i])
	//    {
	//        int j = e[i];
	//        f[u] += dfs(j);
	//    }
	//    return f[u];
	//}
}
int main()
{
    int ans = 0;
    memset(h,-1,sizeof h);
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        b[in]++;
        out[a]++;
    }
    for(int i=1; i<=n; i++)
    {
        if(!in[i] && out[i]) //入度为0,但是出度不为0;因为从1跑到n,当不存在这个边时候也会返回1,所以加入限制条件再记忆化搜索!
        {
            ans += dfs(i);
        }
    }
    printf("%d\n",ans);
    return 0;
}

不记忆化搜索,普通的dfs两种写法!

//以洛谷P1434 [SHOI2002]滑雪为例:
第一种没有递归中点,限制条件再递归下去!
区别不大!可以dfs时候可以像bfs一样加一个step
#include<iostream>
#include<cstring>
using namespace std;
const int N = 309;
int a[N][N],vis[N][N];
int n,m;
const int dx[] = {-1,0,0,1};
const int dy[] = {0,1,-1,0};
int ans,res;
void dfs(int x,int y)
{
    int nowx,nowy;
    for(int i=0; i<4; i++)
    {
        nowx = x + dx[i];
        nowy = y + dy[i];
        if(!vis[nowx][nowy] && nowx>=1 && nowx <=n && nowy >=1 && nowy <=m && a[nowx][nowy] < a[x][y])
        {
            vis[nowx][nowy] = 1;
            ans++;
            //cout<<"nowx = "<<nowx<<" nowy = "<<nowy<<" ans="<<ans<<endl;
            res = max(res,ans);
            dfs(nowx,nowy);
            ans--;
            vis[nowx][nowy] = 0;
        }
    }
}
int main()
{
    ios_base :: sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    cin >> n >> m;
    ans = 1;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++) cin >> a[i][j];
    }
    res = 1;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            ans = 1;
            dfs(i,j);
            //cout<<"res = "<<res<<endl;
        }
    }
    cout<<res<<endl;
    return 0;
}
第二种主动判断递归的终点!
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
int n,m;
int vis[109][109],a[109][109];
int ans;
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
bool check(int x,int y)
{
    int nowx,nowy;
    for(int i=0; i<4; i++)
    {
        nowx = x + dir[i][0];
        nowy = y + dir[i][1];
        if(nowx >= 1 && nowx <= n && nowy >= 1 && nowy <= m)
        {
            if(!vis[nowx][nowy] && a[nowx][nowy] < a[x][y]) return true;
        }
    }
    return false;
}
void dfs(int x,int y,int step)
{
    if(!check(x,y))
    {
        ans = max(ans,step);
        return;
    }
    for(int i=0; i<4; i++)
    {
        int xx,yy;
        xx = x+dir[i][0];
        yy = y + dir[i][1];
        if(xx <= n && xx >= 1 && yy <= m && yy >= 1)
        {
            if(!vis[xx][yy] && a[xx][yy] < a[x][y])
            {
                vis[xx][yy] = 1;
                dfs(xx,yy,step+1);
                vis[xx][yy] = 0;
            }
        }
    }
}
int main()
{
    cin >> n >> m;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++) cin >> a[i][j];
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            vis[i][j] = 1;
            dfs(i,j,1);
            vis[i][j] = 0;
        }
    }
    printf("%d\n",ans);
    return 0;
}


acwing 2067 走方格

//普通TLE版暴搜!
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100;
int n,m;
int f[N][N],ans;
const int dx[] = {1,0};
const int dy[] = {0,1};
void dfs(int x,int y)
{
    if(x == n && y == m)
    {
        ans++;
        return;
    }
    for(int i=0; i<2; i++)
    {
        int xx = x + dx[i];
        int yy = y + dy[i];
        if(xx <= n && xx >= 1 && yy <= m && yy >= 1)
        {
           if(xx % 2 != 0 || yy % 2 != 0) dfs(xx,yy);
        }
        
    }

}
int main()
{
    ios_base :: sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    cin >> n >> m;
    dfs(1,1);
    cout<<ans<<endl;
    return 0;
}
//记忆化搜索
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100;
int n,m;
int f[N][N],ans;
const int dx[] = {1,0};
const int dy[] = {0,1};
int dfs(int x,int y)
{
    if(x == n && y == m) return 1;
    if(f[x][y]) return f[x][y];
    //f[x][y] = 1;
    for(int i=0; i<2; i++)
    {
        int xx = x + dx[i];
        int yy = y + dy[i];
        if(xx & 1 || yy & 1)
        {
            if(xx <= n && xx >= 1 && yy <= m && yy >= 1)
            f[x][y] += dfs(xx,yy);
        }
    }
    return f[x][y];
}
int main()
{
    ios_base :: sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    cin >> n >> m;
    //vis[1][1] = 1;
    cout<<dfs(1,1)<<endl;
    return 0;
}