@(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;
}