P6759 [USACO2006 OPEN] 县集市 The County Fair

# [USACO2006 OPEN] 县集市 The County Fair

## 题目描述

每年,FJ 都喜欢去参加县集市,集市上有 $n$ 个展位,每个摊位 $i$ 都会在当天的特定时间 $p_i$ 发放精美的礼品。FJ 已经听说了这一点,他希望能收集尽可能多的礼品和他的奶牛们一起分享。要想获得摊位 $i$ 发放的礼品,FJ 必须确保时间点 $p_i$ 时位于摊位 $i$。

为了获得尽可能多的礼品,FJ 进行了一番详细的调查,通过调查FJ确定了从摊位 $i$ 到摊位 $j$ 所花费的时间 $t_{i,j}$。集市的布局很不寻常,这会导致,FJ如果在从 $i$ 到 $j$ 的过程中选择从其他摊位绕行,可能会比直接从 $i$ 到 $j$ 所花费的时间更少,然而我们耿直的 FJ 从来不这么做,如果他想从摊位 $i$ 到摊位 $j$,他一定会花 $t_{i,j}$ 的时间从 $i$ 走到 $j$。另外由于集市所在地崎岖不平,所以 $t_{i,j}$ 可能与 $t_{j,i}$ 不相同。

FJ 在时间 $0$ 时,位于 $1$ 号摊位,请计算他最多可以收集多少奖品。

## 输入格式

第 $1$ 行:一个整数 $n$,表示摊位的数量。

第 $2$ 行:共 $n$ 个整数,其中第 $i+1$ 的正数 $p_i$ 表示摊位 $i$ 发放礼品的时间。

第 $n+2$ 到第 $n^2+n+1$ 行:共 $n^2$ 行,第一个 $n$ 行描述了 FJ 从摊位 $1$ 走到到摊位 $1$...$n$ 所需时间($t_{1,1},t_{1,2}, ...t_{1,n}$),接下来的 $n$ 行描述了 FJ 从摊位 $2$ 走到摊位 $1$...$n$ 所需时间($t_{2,1},t_{2,2}, ...t_{2,n}$),以此类推,最后的 $n$ 行描述了 FJ 从摊位 $n$ 走到摊位 $1$...$n$ 所需要的时间 $t_{n,1},t_{n,2}, ...t_{n,n}$。对于任意摊位 $i$,$t_{i,i}=0$。

## 输出格式

一行:一个整数,表示 FJ 最多可以领取到的奖品数量。

## 样例 #1

### 样例输入 #1

```
4
13
9
19
3
0
10
20
3
4
0
11
2
1
15
0
12
5
5
13
0
```

### 样例输出 #1

```
3
```

## 提示

#### 样例说明

样例中集市上共有 $4$ 个摊位。$1$ 号摊位在时间 $13$ 发放礼品,$2$ 号摊位在时间 $9$ 发放礼品,$3$ 号摊位在时间 $19$ 发放礼品,$4$ 号摊位在时间 $3$ 发放礼品。

FJ 首先从 $1$ 号摊位走到 $4$ 号摊位,用时 $3$,并在时间 $3$ 到达,正好可以领取到奖品,接着他从摊位 $4$ 走到摊位 $2$ ,用时 $5$,并在时间 $8$ 到达,在等待 $1$ 个时间点后可以领取 $2$ 号摊位的礼品,接着他从 $2$ 号摊位走到 $1$ 号摊位,用时 $4$,并在时间 $13$ 到达,从而可以收集到第 $3$ 个礼品。

#### 数据规模与约定

对于 $100\%$ 的数据,$1\le n\le 400$,$0\le p_i\le 10^9$,$1\le t_{i,j}\le 10^6$。

数据来自 darkbzoj。

#include <bits/stdc++.h>	//万能头
using namespace std;	//命名空间
struct node	//用结构体做的,也可以采用其他方法
{
	int tim , num;
}a[1001];	//结构体数组
bool cmp(node x , node y)	//后面sort要用到的排序规则
{
	return x.tim < y.tim;
}
int f[1001] , t[1001][1001];	//一些数组
int main()
{
	int n , ans;	//两个变量,一个输入,一个输出
	cin >> n;	//输入
	a[0].tim = 0;	//初始化a[0]的tim
	a[0].num = 1;	//初始化a[0]的num
	for(int i = 1; i <= n; i++)	//一直到第45行都是输入
	{
		cin >> a[i].tim;
		a[i].num = i;
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			cin >> t[i][j];
		}
	}
	sort(a + 1 , a + n + 1 , cmp);	//排序
	for(int i = 1; i <= n; i++)	//其实真正的代码就这一个循环,过一遍,处理一遍
	{
		for(int j = 0; j < i; j++)
		{
			if((t[a[j].num][a[i].num] + a[j].tim) <= a[i].tim)
			{
				f[i] = max(f[i] , f[j] + 1);
			}
		}
	}
	for(int i = 1; i <= n; i++)	//打一遍擂台找最大值
	{
		ans = max(ans , f[i]);
	}
	cout << ans << endl;	//输出
	return 0;	//完美结束Perfect
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值