UVa 10269 Adventure of Super Mario (Floyd + DP + BFS)

题意:有A个村庄,B个城市,m条边,从起点到终点,找一条最短路径。但是,有一种工具可以使人不费力的移动L个长度,但始末点必须是城市或村庄。这种工具有k个,每个只能使用一次,并且在城市内部不可使用,但在村庄内部可使用。另外,在城市或村庄内部的时间不计。

析:先预处理出来使用工具能到达的距离,这个可以用Floyd 来解决,然后f[i][u] 表示到达 u 还剩下 i 次工具未用,然后用bfs就可以很简单的解决。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(i,x,n)  for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 100 + 10;
const int maxm = 1e5 + 10;
const int mod = 50007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, -1, 0, 1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
  return r >= 0 && r < n && c >= 0 && c < m;
}

int dp[maxn][maxn];
int f[12][maxn];

int main(){
  int T;  cin >> T;
  while(T--){
    int A, B, L, K;
    scanf("%d %d %d %d %d", &A, &B, &m, &L, &K);
    ms(dp, INF);
    while(m--){
      int u, v, c;  scanf("%d %d %d", &u, &v, &c);
      dp[u][v] = dp[v][u] = min(c, dp[u][v]);
    }
    FOR(k, 1, A+1)  FOR(i, 1, A+B+1)  FOR(j, 1, A+B+1)
      dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
    ms(f, INF);  f[K][A+B] = 0;
    queue<P> q;  q.push(P(K, A+B));
    while(!q.empty()){
      P p = q.front();  q.pop();
      int u = p.se, i = p.fi;
      for(int v = 1; v < A+B; ++v){
        if(dp[u][v] == INF || u == v)  continue;
        if(f[i][v] > f[i][u] + dp[u][v]){
          f[i][v] = f[i][u] + dp[u][v];
          q.push(P(i, v));
        }
        if(i && f[i-1][v] > f[i][u] && L >= dp[u][v]){
          f[i-1][v] = f[i][u];
          q.push(P(i-1, v));
        }
      }
    }
    int ans = INF;
    for(int i = 0; i <= K; ++i)  ans = min(ans, f[i][1]);
    printf("%d
", ans);
  }
  return 0;
}

  

原文地址:https://www.cnblogs.com/dwtfukgv/p/7742618.html