UVa1601

---恢复内容开始---

这道题的题解很多,所以就不用说明了。

下面便是单dfs与双dfs的代码 

 900ms

// UVa 1601
// bfs(原始) 
#include 
#include 
#include  
#include  
using namespace std; 
const int maxc = 20; 
const int maxn = 256; 

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

int w, h, n; 
int s[3], t[3];
int deg[maxn], G[maxn][5]; 

int get_ID(int a, int b, int c) {
  return (a<<16)|(b<<8)|c; 
}

bool is_conflict(int a, int b, int a1, int b1) {
  return (a1 == b1) || (a == b1 && b == a1);     
}

int dist[maxn][maxn][maxn]; 

int bfs() {
  queue<int> q;
  memset(dist, -1, sizeof(dist));   
  q.push(get_ID(s[0], s[1], s[2])); 
  dist[s[0]][s[1]][s[2]] = 0;
  while (!q.empty()) {
    int u = q.front(); q.pop();
    int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff; 
    if (a == t[0] && b == t[1] && c == t[2]) return dist[a][b][c]; 
    for (int i = 0; i < deg[a]; ++i) {
      int a1 = G[a][i]; 
      for (int j = 0; j < deg[b]; ++j) {
        int b1 = G[b][j]; 
        if (is_conflict(a, b, a1, b1)) continue; 
        for (int k = 0; k < deg[c]; ++k) {
          int c1 = G[c][k];
          if (is_conflict(a, c, a1, c1)) continue; 
          if (is_conflict(b, c, b1, c1)) continue; 
          if (dist[a1][b1][c1] != -1) continue;  
          dist[a1][b1][c1] = dist[a][b][c] + 1;
          q.push(get_ID(a1, b1, c1));  
        }
      } 
    }
  }
  return -1; 
}

int main() {
  while (scanf("%d%d%d\n", &w, &h, &n) == 3 && n) {
    int cnt = 0, x[maxn], y[maxn], id[maxc][maxc];
    char input[maxc][maxc]; 
    for (int i = 0; i < h; ++i)
      fgets(input[i], maxc, stdin); 
    for (int i = 0; i < h; ++i) 
      for (int j = 0; j < w; ++j) 
        if (input[i][j] != '#') {
          x[cnt] = i; y[cnt] = j; id[i][j] = cnt; 
          if (islower(input[i][j])) s[input[i][j]-'a'] = cnt; 
          else if (isupper(input[i][j])) t[input[i][j]-'A'] = cnt; 
          cnt++; 
        }
    for (int i = 0; i < cnt; ++i) {
      deg[i] = 0;
      for (int j = 0; j < 5; ++j) {
        int x1 = x[i]+dx[j], y1 = y[i]+dy[j];
        if (input[x1][y1] != '#') G[i][deg[i]++] = id[x1][y1];
      }
    }
    if (n <= 2) { deg[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++; }
    if (n <= 1) { deg[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++; } 
    printf("%d\n", bfs()); 
  }
  return 0;
}

750ms

// UVa 1601 
// 双向bfs
#include 
#include  
#include  
#include  
using namespace std; 
const int maxc = 20; 
const int maxn = 256; 

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

int w, h, n;
int deg[maxn], G[maxn][5]; 

int s[3], t[3]; 

int ID(int a, int b, int c) { return (a<<16)|(b<<8)|c; }

bool is_conflict(int a, int b, int a1, int b1) {
  return (a1 == b1) || (a == b1 && b == a1);    
}

int ds[maxn][maxn][maxn];
int dt[maxn][maxn][maxn];  

int dfs() {
  queue<int> qs, qt; 
  qs.push(ID(s[0], s[1], s[2])); 
  qt.push(ID(t[0], t[1], t[2])); 
  memset(ds, -1, sizeof(ds));
  memset(dt, -1, sizeof(dt));
  ds[s[0]][s[1]][s[2]] = dt[t[0]][t[1]][t[2]] = 0;
  while (!qs.empty() && !qt.empty()) {
    {
      int u = qs.front(); qs.pop(); 
      int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff;
      for (int i = 0; i < deg[a]; ++i) {
        int a1 = G[a][i]; 
        for (int j = 0; j < deg[b]; ++j) {
          int b1 = G[b][j]; 
          if (is_conflict(a, b, a1, b1)) continue;  
          for (int k = 0; k < deg[c]; ++k) {
            int c1 = G[c][k];
            if (is_conflict(a, c, a1, c1)) continue; 
            if (is_conflict(b, c, b1, c1)) continue;
            if (ds[a1][b1][c1] == -1) { ds[a1][b1][c1] = ds[a][b][c] + 1; qs.push(ID(a1, b1, c1)); } 
            if (dt[a1][b1][c1] != -1) return ds[a1][b1][c1] + dt[a1][b1][c1];      
          }
        }
      }
    }
    {
      int u = qt.front(); qt.pop(); 
      int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff;
      for (int i = 0; i < deg[a]; ++i) {
        int a1 = G[a][i]; 
        for (int j = 0; j < deg[b]; ++j) {
          int b1 = G[b][j]; 
          if (is_conflict(a, b, a1, b1)) continue;  
          for (int k = 0; k < deg[c]; ++k) {
            int c1 = G[c][k];
            if (is_conflict(a, c, a1, c1)) continue; 
            if (is_conflict(b, c, b1, c1)) continue;
            if (dt[a1][b1][c1] == -1) { dt[a1][b1][c1] = dt[a][b][c] + 1; qt.push(ID(a1, b1, c1)); }
            if (ds[a1][b1][c1] != -1) return dt[a1][b1][c1] + ds[a1][b1][c1];      
          }
        }
      }
    }
  }
  return -1; 
} 

int main() { 
  while (scanf("%d%d%d\n", &w, &h, &n) == 3 && n) {    
    char input[maxc][maxc]; 
    int cnt = 0, x[maxn], y[maxn], id[maxc][maxc]; 
    for (int i = 0; i < h; ++i) 
      fgets(input[i], maxc, stdin);  
    for (int i = 0; i < h; ++i) 
      for (int j = 0; j < w; ++j) if (input[i][j] != '#') {
        x[cnt] = i; y[cnt] = j; id[i][j] = cnt; 
        if (islower(input[i][j])) s[input[i][j]-'a'] = cnt; 
        else if (isupper(input[i][j])) t[input[i][j]-'A'] = cnt; 
        cnt++; 
      }
    for (int i = 0; i < cnt; ++i) {
      deg[i] = 0; 
      for (int j = 0; j < 5; ++j) {
        int x1 = x[i]+dx[j], y1 = y[i]+dy[j];
        if (input[x1][y1] != '#') { G[i][deg[i]++] = id[x1][y1]; }     
      }
    }
    if (n <= 2) { deg[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++; } 
    if (n <= 1) { deg[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++; }
    printf("%d\n", dfs()); 
  }
  return 0;
}

单dfs的查询节点大概是 n ^ len

双dfs的查询节点大概是 2 * n ^ (len / 2) 

n, len越大优化程度越高

转载于:https://www.cnblogs.com/yifeiWa/p/11019233.html

你可能感兴趣的:(UVa1601)