Fork me on GitHub

贪心算法_旅行

Problem D. 旅行

时间限制 1000 ms
内存限制 128 MB

题目描述

某趟列车的最大载客容量为V人,沿途共有n个停靠站,其中始发站为第1站,终点站为第n站。
在第1站至第n-1站之间,共有m个团队申请购票搭乘,若规定:
(1)对于某个团队的购票申请,要么全部满足,要么全部拒绝,即不允许只满足部分。(2)每个乘客的搭乘费用为其所乘站数。
问:应如何选择这些购票申请,能使该趟列车获得最大的搭乘费用?
其中,每个团队的购票申请格式是以空格分隔的三个整数:a b t,即表示有t个人需要从第a站点乘至第b站点(注:每个团队的所有人员都必须同时在a站上车,且必须同时在后面的b站下车)。

输入数据

输入数据有若干行。
第 1 行只有三个整数 n,m,v,分别表示站点数、申请数、列车的最大载客容量。这三个整数之间都以一个空格分隔。
第 2 行至第 m+1 行,每行有三个整数,中间都以一个空格分隔。其中第 k+1 行的三个整数 a,b,t 表示第 k 个申请,含义为:有 t 个人需要从第 a 站乘至第 b 站。
其中:1 ≤ n ≤ 10;1 ≤ m ≤ 18

输出数据

输出数据只有一行,该行只有一个整数,为该列车能获得的最大搭乘费用。

样例输入

1
2
3
4
3  3  5
1 2 2
2 3 5
1 3 4

样例输出

1
8

题解

这道题与0-1背包问题类似。直接枚举所有可能的方案数,对于每一个团队,只有两个选择,搭乘与不搭乘,可以采用二进制0与1枚举的方式。由于团队申请数目m最多只有18个,所以最多有2^18种方案。对于每一种方案,统计每一站车上的总人数,如果某一站车上总人数超过了列车的最大载客容量v,那么此方案不可行;否则,比较搭乘费用,取最大的搭乘费用即可。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

int n, m, v, a[20], b[20], t[20], num[25];
long long cost = 0, temp;
bool flag;
int i, j;

int main() {
cin >> n >> m >> v;
for (i = 0; i < m; i++) {
cin >> a[i] >> b[i] >> t[i];
}
// 枚举二进制方案数
for (i = 0; i < (1 << m); i++) {
// 变量的初始化
temp = 0;
flag = true;
memset(num, 0, sizeof(num));
// 判断决定每一个团队是否可以搭乘
for (j = 0; j < m; j++) {
if (i & (1 << j)) {
num[a[j]] += t[j];
num[b[j]] -= t[j];
temp += (b[j] - a[j]) * t[j];
}
}
// 统计每一站车上的总人数,如果大于容量,就不满足条件
for (j = 1; j <= n; j++) {
num[j] += num[j - 1];
if (num[j] > v) {
flag = false;
}
}
// 满足条件则取最大搭乘费用
if (flag) {
cost = max(cost, temp);
}
}
cout << cost << endl;
return 0;
}
0%