当前位置 : 主页 > 网页制作 > HTTP/TCP >

The 2019 Asia Yinchuan First Round Online Programming F. Moving On

来源:互联网 收集:自由互联 发布时间:2021-06-16
t题目链接:https://nanti.jisuanke.com/t/41290 思路:题目意思很容易想到floyd,但是由于危险度的限制,我们该怎么跑floyd呢。 一开始理解错题目了,以为u-v包括终点起点都不能超过给的危险

t题目链接:https://nanti.jisuanke.com/t/41290

思路:题目意思很容易想到floyd,但是由于危险度的限制,我们该怎么跑floyd呢。

一开始理解错题目了,以为u->v包括终点起点都不能超过给的危险度,不过看样例,好像只需要中间的城市不能超过危险度。

我们可以这么想,每个城市都有一个危险度,而floyd算法的本质是i到j经过前k个城市的转移,得到多源最短路,那么我们不妨

记录城市的编号和危险度,然后按城市的危险度排序,重新编号,危险度小的先跑floyd,然后f[k][i][j]表示经过前k个城市的最短路,

那么我们得出  f[k][i][j] = min(f[k-1][i][j],f[k-1][i][num[k]] + f[k-1][num[k][j]),从危险度小的推到危险度大的。

对于每个询问,我们只需要遍历按危险度编号的n个城市跑出的f[k][i][j],直到遍历到城市的危险度超出了危险度上限的那个f[k][u][v],

就是我们的答案了。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <cmath>
using namespace std;

typedef long long LL;
#define inf 1e9
#define rep(i, j, k) for (int i = (j); i <= (k); i++)
#define rep__(i, j, k) for (int i = (j); i < (k); i++)
#define per(i, j, k) for (int i = (j); i >= (k); i--)
#define per__(i, j, k) for (int i = (j); i > (k); i--)

const int N = 210;
int f[N][N][N];
int n,q;
int u,v,w;

struct node{
    int id;
    int ATK;

    friend bool operator<(const node& a,const node& b){
        return a.ATK < b.ATK;
    }
}W[N];

int main(){

    int T;
    scanf("%d",&T);

    rep(o,1,T){
        scanf("%d%d",&n,&q);

        rep(i,1,n){
            W[i].id = i;
            scanf("%d",&W[i].ATK);
        }

        sort(W + 1,W + n + 1);

        rep(i,1,n) rep(j,1,n){
            if(i == j) f[0][i][j] = 0;
            else f[0][i][j] = inf;
        }

        rep(i,1,n) rep(j,1,n){
            scanf("%d",&w);
            f[0][i][j] = w;
        }

        // rep(i,1,n) cout << W[i].ATK << endl;

        // rep(i,1,n){
        //     rep(j,1,n) cout << f[0][i][j] << " ";
        //     cout << endl;
        // }

        rep(k,1,n) rep(i,1,n) rep(j,1,n){
            f[k][i][j] = min(f[k-1][i][j],f[k-1][i][W[k].id]+f[k-1][W[k].id][j]);
        }

        printf("Case #%d:\n",o);

        int tmp;
        rep(i,1,q){
            scanf("%d%d%d",&u,&v,&w);
            tmp = 0;
            rep(j,1,n) if(W[j].ATK <= w) tmp = j;
            printf("%d\n",f[tmp][u][v]);
        }
    }

    getchar();getchar();
    return 0;
}
网友评论