soj 2505: The County Fair(离散化 + 记忆化搜索)

@(K ACMer)
题意
有n个展台,你初始时刻在1号展台,时间为0.然后每个展台都会在一个固定的时间 p(i)(0<p(i)<1e9) 发奖品,从起点出发,你能前往任何展台,但是必须在该点等到p(i)时间拿到奖品,然后再离开,从每两个展台相互之间的转移需要时间 T(i,j) .问你最多可以得到多少个奖品.
(注:这里除了没有必要在第一个展台待到它发奖品的时间,其它都要).
分析:
我们很容易想到一个暴力搜索

dfs(a,t)=min(dfs(j,p(a)+T(a,j))+1)(j=0....n|j!=a)
,只需要记忆化一下,但是这里记忆化不可行,因为 p(i) 的值太大了,数组存不下,所以我们先离散化一下.
离散的时候排序,去重一下即可.

code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int mod = int(1e9) + 7, INF = 1e10, maxn = 4e2 + 40;
int n, G[maxn][maxn], p[maxn], maxp, hashs[maxn], m, num, dp[maxn][maxn];


int getid(int x) {
    return lower_bound(hashs, hashs + num, x) - hashs;
}

int dfs(int a, int t) {
    if (t > p[a]) return 0;
    int tt = getid(t);
    if (dp[a][tt] != -1) return dp[a][tt];
    int maxs = 0;
    for (int i = 0; i < n; i++) {
        if (i == a) continue;
        maxs = max(maxs, dfs(i, p[a] + G[a][i]));
    }
    return dp[a][tt] = maxs + 1;
}


int main(void) {
    while (~scanf("%d", &n)) {
        m = 0;
        memset(dp, -1, sizeof(dp));
        for (int i = 0; i < n; i++)
            scanf("%d", &p[i]), hashs[m++] = p[i];
        sort(hashs, hashs + m);

        num = 1;
        for (int i = 1; i < m; i++)
            if (hashs[i] != hashs[i - 1]) hashs[num++] = hashs[i];

        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                scanf("%d", &G[i][j]);
        int ans = dfs(0, p[0]);
        for (int i = 1; i < n; i++) {
            ans = max(ans, dfs(i, G[0][i]));
        }
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(soj 2505: The County Fair(离散化 + 记忆化搜索))