dfs

ABC 236 D - Dance

题目链接
https://atcoder.jp/contests/abc236/tasks/abc236_d

解析

  • 有点dfs与剪枝的意味??不清楚是不是叫剪枝
  • 就是说通过设定一些枚举规则,使得对于本问题来说,没有枚举少一些情况
  • 枚举规则可以参考官方题解
  • 大概思路就是一层dfs枚举两个数,第一维是剩余数中最小的,第二维是剩余数中的随便一个,可以学习一下一对一对地搞dfs的代码思路。

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
 
using namespace std;
 
typedef pair<int, int> PII;
 
const int N = 30;
 
vector<PII> vec;
int ans, n, res;
int g[N][N];
bool st[N];
 
void dfs(int u)
{
    if(u == n + 1){
        int ans = 0;
        for(auto t : vec) {
            ans ^= g[t.first][t.second];
            //cout << t.first << ' ' << t.second << "  ";
        }
        //puts("");
        res = max(res, ans);
        return;
    }
    int mmin;
    for(int i = 1; i <= 2 * n; i ++){
        if(!st[i]){
            mmin = i;
            break;
        }
    }
    st[mmin] = true;
 
    for(int i = 1; i <= 2 * n; i ++){
        if(!st[i]){
            vec.push_back({mmin, i}); st[i] = true;
            dfs(u + 1);
            vec.pop_back(); st[i] = false;
        }
    }
    st[mmin] = false;
}
 
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= 2 * n; i ++){
        for(int j = i + 1; j <= 2 * n; j ++){
            scanf("%d", &g[i][j]);
        }
    }
    dfs(1);
    printf("%d\n", res);
 
    return 0;
}

842.排列数字

题目链接
https://www.acwing.com/problem/content/844/

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10;

int n;
bool st[N];
int f[N];

void dfs(int u)
{
    if(u == n + 1){
        for(int i = 1; i <= n; i ++) printf("%d ", f[i]);
        puts("");
    }
    
    for(int i = 1; i <= n; i ++){
        if(!st[i]){
            st[i] = true;
            f[u] = i;
            dfs(u + 1);
            st[i] = false;
        }
    }
}

int main()
{
    scanf("%d", &n);
    
    dfs(1);
    
    return 0;
}

285. 没有上司的舞会

题目链接
https://www.acwing.com/problem/content/287/

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 6010;

int n;
int h[N], e[N], ne[N], idx;
int happy[N];
bool has_father[N];
int f[N][2];

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void dfs(int u)
{
    f[u][1] = happy[u];
    
    for(int i = h[u]; i != -1; i = ne[i]){
        int j = e[i];
        
        dfs(j);
        
        f[u][0] += max(f[j][0], f[j][1]);
        f[u][1] += f[j][0];
    }
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d", &happy[i]);
    
    memset(h, -1, sizeof h);
    for(int i = 1; i < n; i ++){
        int a, b;
        scanf("%d%d", &a, &b);
        add(b, a);
        has_father[a] = true;
    }
    
    int root = 1;
    while(has_father[root]) root ++;
    
    dfs(root);
    
    printf("%d\n", max(f[root][0], f[root][1]));
    
    return 0;
}

901.滑雪

题目链接
https://www.acwing.com/problem/content/903/

解析
记忆化搜索

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 310;

int h[N][N];
int f[N][N];
int m, n;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int dp(int x, int y)
{
    if(f[x][y] != -1) return f[x][y];
    
    f[x][y] = 1;
    for(int i = 0; i < 4; i ++){
        int a = x + dx[i], b = y + dy[i];
        if(a >= 1 && a <= m && b >= 1 && b <= n && h[a][b] < h[x][y])
            f[x][y] = max(f[x][y], dp(a, b) + 1);
    }
    
    return f[x][y];
}

int main()
{
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= m; i ++)
        for(int j = 1; j <= n; j ++)
            scanf("%d", &h[i][j]);
            
    int res = 0;
    memset(f, -1, sizeof f);
    for(int i = 1; i <= m; i ++)
        for(int j = 1; j <= n; j ++)
            res = max(res, dp(i, j));
    
    printf("%d\n", res);
    
    return 0;
}

843. n皇后问题

题目链接
https://www.acwing.com/problem/content/845/

解析
感觉老是把递归出口写少一层

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 20;

int n;
char a[N][N];
bool row[N], col[N], dg[N], udg[N];

void dfs(int u)
{
    if(u == n + 1){
        for(int i = 1; i <= n; i ++) printf("%s\n", a[i] + 1);
        puts("");
        return;
    }
    
    for(int i = 1; i <= n; i ++){
        if(!col[i] && !dg[u + i] && !udg[n - u + i]){
            a[u][i] = 'Q';
            col[i] = dg[u + i] = udg[n - u + i] = true;
            dfs(u + 1);
            col[i] = dg[u + i] = udg[n - u + i] = false;
            a[u][i] = '.';
        }
    }
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            a[i][j] = '.';
    
    dfs(1);
    
    return 0;
}

1875. 贝茜的报复

题目链接
https://www.acwing.com/problem/content/1877/

解析
咱就是说吧dfs想简单了,写了个复杂度和7层循环不相上下的dfs,应该先对题目式子进行化简,转化成对于每个数奇偶的dfs,记录每个字母的奇偶取值的个数,然后算出最终答案。
但其实如果只是暴搜每个数的奇偶状态,可以转化为二进制暴力枚举。

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;

const int N = 10;

int n;
map<char, int> mp1;
map<char, int> mp2;
int ans[N];
int cnt;

string str = "BESIOMG";

void dfs(int u, int x)
{
    if(u == 7){
        if((ans[0] + ans[3]) % 2 && (ans[6] + ans[4] + ans[1] + ans[2]) % 2 && ans[5] % 2) return;
    cnt += x;
    return;
}
    
    ans[u] = 1;
    dfs(u + 1, x * mp1[str[u]]);
    ans[u] = 2;
    dfs(u + 1, x * mp2[str[u]]);
}

int main()
{
    scanf("%d\n", &n);
    while(n --)
    {
        char op;
        int x;
        scanf("%c %d\n", &op, &x);
        if(x % 2) mp1[op] ++;
        else mp2[op] ++;
    }
    
    dfs(0, 1);
    
    printf("%d\n", cnt);
    
    return 0;
}

1929. 镜子田地

题目链接
https://www.acwing.com/problem/content/1931/

解析

  • 整体框架是暴力枚举所有的入射光线,计算每种情况下的反射数,取最大值。

  • 计算反射数要进行搜索,此处用的dfs。(感觉bfs好像也行?)

  • 搜索的困难在于判断到达某一格子后给出出射方向,本题通过异或的方式对方向的判断做了很好的简化。
    image

  • dfs过程中要传的参数比较多,总而言之就是会用到的都要传。

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

char a[N][N];
int n, m;
int ans;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};  //0、1、2、3

void dfs(int x, int y, int d, int u){
    ans = max(ans, u);
    
    int nx, ny, nd;
    if(a[x][y] == '/') nd = d ^ 1;
    else nd = d ^ 3;
    
    nx = x + dx[nd], ny = y + dy[nd];
    if(nx >= 1 && nx <= n && ny >= 1 && ny <= m)
        dfs(nx, ny, nd, u + 1);
        
    return;
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%s", a[i] + 1);
    //for(int i = 1; i <= n; i ++) cout << a[i] + 1 << endl;
    
    //水平方向射入的光线
    for(int i = 1; i <= n; i ++){
        dfs(i, 1, 1, 1);
        dfs(i, m, 3, 1);
    }
    
    //垂直方向射入的光线
    for(int i = 1; i <= m; i ++){
        dfs(1, i, 2, 1);
        dfs(n, i, 0, 1);
    }
    
    printf("%d\n", ans);
    
    return 0;
}

2005. 马蹄铁

题目链接
https://www.acwing.com/problem/content/2007/

解析
dfs。感觉想明白传什么参数很重要,庆祝我也可以写dfs嘻嘻(逛超市去喽

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10;

int n;
char a[N][N];
bool st[N][N];
int ans = 0;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

void dfs(int x, int y, int l, int r){
    if(l == r && l > 0){
        ans = max(ans, l + r);
        return;
    }
    
    for(int i = 0; i < 4; i ++){
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 1 || nx > n || ny < 1 || ny > n) continue;
        if(st[nx][ny]) continue;
        if(r > 0 && a[nx][ny] == ')'){
            st[nx][ny] = true;
            dfs(nx, ny, l, r + 1);
            st[nx][ny] = false;
        }
        if(r == 0){
            st[nx][ny] = true;
            if(a[nx][ny] == '(') dfs(nx, ny, l + 1, r);
            st[nx][ny] = false;
            
            st[nx][ny] = true;
            if(a[nx][ny] == ')') dfs(nx, ny, l, r + 1); 
            st[nx][ny] = false;
        }
    }
    return;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%s", a[i] + 1);
    st[1][1] = true;
    if(a[1][1] == '(') dfs(1, 1, 1, 0);
    else dfs(1, 1, 0, 1);
    
    printf("%d\n", ans);
    
    return 0;
}
posted @   小菜珠的成长之路  阅读(163)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示