SOJ 2505 The Country Fair

题意: John 去参加国家展览,每个展台i在P[i]时刻都会有一个抽奖活动,从展台i走到展台j需要花费T[i][j]的时间,John在时刻0在1号站台,john想尽量多的参加抽奖活动,问他最多可以参加多少个抽奖活动.

分析:这道题可以想成John从s号展台出发,然后最后走到e号展台,使其中路线当中抽奖过的展台越多越好.这样可以转化为一个最短路问题,考虑这样建图,如果John在i号展台抽奖,那么他必须提前到达i号展台并等到P[i]时刻,P[i] + T[i][j] <= P[j] 那么John便可以再到j号展台抽奖,则从i到j连一条权值为-1的边,因为John在时刻0在1号展台,可以通过T[0][j] <= P[j] 判断出John第一个可以抽奖的展台,对于每一个可以第一个抽奖的展台s,枚举终点e找到路径最小的path[s][e],这样-path[s][e] + 1就是John可以抽奖的最多的次数.其中求最短路径可以用floyd一次搞定.很经典的图论题.

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 400 + 5;
const int inf = 0x3f3f3f3f;
int dist[maxn][maxn];
int dp[maxn][maxn];
int P[maxn];
int N;
int main()
{
    while(scanf("%d", &N) == 1) {
        for(int i = 0; i < N; i++) {
            scanf("%d", &P[i]);
        }
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                scanf("%d", &dist[i][j]);
            }
        }

        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                if(i == j) dp[i][j] = 0;
                else if(P[i] + dist[i][j] <= P[j]) {
                    dp[i][j] = -1;
                } else {
                    dp[i][j] = inf;
                }
            }
        }

        for(int k = 0; k < N; k++) {
            for(int i = 0; i < N; i++) {
                for(int j = 0; j < N; j++) {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
                }
            }
        }

        int ans = 0;
        for(int i = 0; i < N; i++) {
            if(dist[0][i] <= P[i]) {
                for(int j = 0; j < N; j++) {
                    if(dp[i][j] > 0) continue;
                    else {
                        ans = max(ans, -dp[i][j] + 1);
                    }
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(SOJ 2505 The Country Fair)