zoukankan      html  css  js  c++  java
  • UVa11882最大的数(dfs+剪枝)

    今天说一道题吧!

    题意:

    看洛谷https://www.luogu.org/problemnew/show/UVA11882

    思路:

    根据这道题R,C不是特别大我们可以考虑使用搜索的方法去做,那么根据R*C=30我们知道普通的dfs会超时,

    所以必须考虑剪枝。

    怎么剪枝?如果我们只看数字的大小是不科学的(例如99与10000),只看位数也不行,

    所以比较的时候我们既需要看位数同时需要看大小,这可怎么办啊?

    当时我就困在这一点了,我发现同时追求这两个是无法剪枝的。

    那么就剪不了了吗?

    当然不会,既然同时满足不了,那么我们在位数相同时比较数字可以吗?可以的。

    那位数又怎么办呢?

    我们可以采用枚举位数,然后根据位数来确定数字。

    将一个问题分开去想,能够剪枝并且解决问题。

    于是我们说一说实现(代码)

    我们首先类似迭代加深搜索来确定位数,然后在位数确定的时候填数。

    如果能够满足这个位数,那么后面我们就不在去枚举比较小的位数了(位数从大到小枚举)(剪枝1)

    如果我们得到了当前的最优解,那么对于某个时刻来说,我们需要判断已经确定的部分是否能够大于或者等于最优解。(剪枝2)

    这样我们就不会超时了,下面是代码

    // UVa 11882 
    // 迭代加深 + 剪枝
    // 剪枝策略:将之前最优解记录下来,判断当前来讲是否优于最优解
    #include <cstdio> 
    #include <cstring> 
    using namespace std; 
    
    const int maxn = 20; 
    char square[maxn][maxn], ans[50], num[50]; 
    int R, C, vis[maxn][maxn], maxd, ok;  
    
    bool cmp(int depth) {
      if (strlen(ans) == 0) return true;  
      for (int i = 0; i < depth; ++i) if (num[i] != ans[i]) return num[i] > ans[i]; 
      return true;     
    } 
    
    const int dx[] = {-1, 1, 0, 0}; 
    const int dy[] = {0, 0, -1, 1}; 
    
    void dfs(int curx, int cury, int depth) {
      if (depth == maxd) {
        ok = 1;
        num[depth] = ''; 
        if (cmp(depth)) memcpy(ans, num, sizeof(num)); 
        return; 
      }
      for (int i = 0; i < 4; ++i) { 
        int x = curx+dx[i], y = cury+dy[i]; 
        if (x >= 0 && x < R && y >= 0 && y < C) { 
          if (vis[x][y] == 1 && square[x][y] != '#') {
            vis[x][y] = 0; 
            num[depth] = square[x][y]; 
            if (cmp(depth)) dfs(x, y, depth+1); 
            vis[x][y] = 1; 
          }
       }
      }
      return; 
    }
    
    void init() { 
      for (int i = 0; i < R; ++i) 
        for (int j = 0; j < C; ++j) 
          vis[i][j] = 1;
    }
    
    int main() {  
      while (scanf("%d%d", &R, &C) == 2 && R) {
        int cnt = 0;
        for (int i = 0; i < R; ++i) {
          scanf("%s", square[i]);
          for (int j = 0; j < C; ++j) 
            if (square[i][j] != '#') ++cnt; 
        }
        ok = 0; 
        memset(ans, 0, sizeof(ans));
        init();
        for (maxd=cnt; ; --maxd) {
          for (int i = 0; i < R; ++i) 
            for (int j = 0; j < C; ++j)
              if (square[i][j] != '#') {
                num[0] = square[i][j]; 
                vis[i][j] = 0;
                dfs(i, j, 1);
                init(); 
              }
          if (ok) break; 
        }
        printf("%s
    ", ans); 
      }
      return 0;
    }

    不会的留言或者加我qq,我会耐心回答的。

  • 相关阅读:
    hdu2037 经典贪心入门
    hdu1045 dfs
    poj2243 bfs
    poj2488 dfs
    poj1111 DFS
    单词统计
    冲刺第五天
    七周总结学习笔记
    冲刺第四天
    冲刺第三天
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11157949.html
Copyright © 2011-2022 走看看