Traveling by Stagecoach (Poj 2686)

原题链接


思路

由于 \(k\) 的范围只有 \(8\), 很容易想到这题要用一个暴力的方法,我们可以用 状压dp 来解决这个问题。

\(f[i][j]\) 为 当前车票的可选即可为 \(i\) ,并且 当前的位置是 \(j\) 的最小花费,然后进行状态转移即可

SOLUTION

#include <cstdio>
#include <cstring>

const int N = 10, M = 32, INF = 0x3f3f3f3f;

int a[N];
int g[M][M];
double f[1 << N][M];

int n, m, k; 
int s, e; 

void chkmin(int &x, int y) {
  x = (x <= y ? x : y);
}

void chkmin(double &x, double y) {
  x = (x <= y ? x : y);
}

void solve() {

  for(int i = 1; i <= k; i ++ ) scanf("%d", a + i);
  
  memset(g, 0x3f, sizeof g);
  
  for(int i = 0; i < m; i ++ ) {
    int u, v, w; scanf("%d%d%d", &u, &v, &w);
    chkmin(g[u][v], w);
    chkmin(g[v][u], w);
  }

  for(int i = 0; i < 1 << k; i ++ ) {
    for(int j = 0; j <= n; j ++ ) {
      f[i][j] = INF;
    }
  }

  f[(1 << k) - 1][s] = 0;
  
  for(int i = (1 << k) - 1; i > 0; i -- ) {
    for(int u = 1; u <= n; u ++ ) if(f[i][u] <= INF / 2) {
      for(int v = 1; v <= n; v ++ ) if(u != v && g[u][v] <= INF / 2) {
        for(int j = 0; j < k; j ++ ) if(i >> j & 1) {
          chkmin(f[i ^ (1 << j)][v], f[i][u] + (double)g[u][v] / a[j + 1]);
          // printf("> %.3f\n", f[i ^ (1 << j)][v]);
        }
      }
    }
  }

  double ans = 1e18;
  
  for(int i = 0; i < 1 << k; i ++ ) chkmin(ans, f[i][e]);
  
  if(ans >= INF / 2) puts("Impossible");
  else printf("%.3lf\n", ans);
}

int main() {
  
  while(true) {
    scanf("%d%d%d", &k, &n, &m);
    scanf("%d%d", &s, &e);
    if(!k && !n && !m && !s && !e) break;
    solve();
  }

  return 0;
}
posted @ 2022-05-03 15:04  ccz9729  阅读(31)  评论(0编辑  收藏  举报