题目来源:http://poj.org/problem?id=1040

题目大意:

  某运输公司要做一个测试。从A城市到B城市的一条运输线路中有若干个站,将所有站包括A和B在内按顺序编号为0到m。该路线上的一趟列车,乘客最大容量为cap。车开出之前,该趟车会收到来自各个车站的车票订单请求。一个请求包括起点站编号,终点站编号和乘客人数。每张车票的价格为起点到终点之间相隔的站数。在不超载的情况下,求一趟列车能获得的最大收益。对于某一个订单请求,要么接受要么拒绝,不能只接受其中的一部分乘客。

输入:每个测试用例一个数据块。每块的第一行有3个整数:cap:(车的容量), m:(终点城市的编号, 最大为7),n:(订单数,最大为22).接下来的n行每行三个数表示一个订单,三个数分别为起点、终点、人数。

输出:没个测试用例单独一行,输出一个整数表示该趟列车能获得的最大收益。


Sample Input

10 3 4
0 2 1
1 3 5
1 2 7
2 3 10
10 5 4
3 5 10
2 4 9
0 2 5
2 5 8
0 0 0

Sample Output

19
34

由于数据量不算太大,直接用搜索就可以解决。搜索前先对所有订单按起点的顺序进行排序。

不加剪枝的dfs代码,耗时391ms:

 //////////////////////////////////////////////////////////////////////////
// POJ1040 Transportation
// Memory: 264K Time: 391MS
// Language: C++ Result: Accepted
////////////////////////////////////////////////////////////////////////// #include <iostream>
#include <algorithm> using namespace std; int n, m, cap; class Order {
public:
int start;
int destination;
int cnt;
}; Order orders[];
int maxE;
//记录每站有多少个乘客
int pasCnt[]; //比较函数,按start升序,destination降序,cnt降序
bool cmp(const Order &a, const Order &b) {
return a.start == b.start
? (a.destination == b.destination ? (b.cnt < a.cnt) : b.destination < a.destination)
: a.start < b.start;
} void dfs(int i, int now) {
if (now > maxE) {
maxE = now;
}
for (int t = i; t < n; ++t) {
if (pasCnt[orders[t].start] + orders[t].cnt > cap) continue;//reject
for (int j = orders[t].start; j < orders[t].destination; ++j)
//get in
pasCnt[j] += orders[t].cnt;
dfs(t + , now + orders[t].cnt * (orders[t].destination - orders[t].start));
for (int j = orders[t].start; j < orders[t].destination; ++j)
pasCnt[j] -= orders[t].cnt;
}
} int main(void) {
while (true) {
cin >> cap >> m >> n;
if (cap == && m == && n == ) break;
for (int i = ; i < n; ++i)
cin >> orders[i].start >> orders[i].destination >> orders[i].cnt;
//按起点顺序将订单排序
sort(orders, orders + n, cmp);
maxE = ;
memset(pasCnt, , sizeof(pasCnt));
dfs(, );
cout << maxE << endl;
}
system("pause");
return ;
}

(不剪枝DFS)

看了别人剪枝的方法,加上之后,时间瞬间降到16ms.

剪枝方法如下:

每一个order添加两个项v和r。v表示该张订单的收益值。r表示如果选择该选项最多还能获得多少收益,这个值只是一个上界而不是上确界。计算方法是,计算排序后该订单和排在该订单之后的所有订单的收益值之和。因为dfs是按订单顺序依次搜索的,所以当当前收益值加上该订单的r值小于等于已搜到的最大收益,则不必再考虑该订单及以后的订单,因为不可能再得到比已知最大收益更大的收益。

 //////////////////////////////////////////////////////////////////////////
// POJ1040 Transportation
// Memory: 236K Time: 16MS
// Language: C++ Result: Accepted
////////////////////////////////////////////////////////////////////////// #include <iostream>
#include <algorithm> using namespace std; int n, m, cap; class Order {
public:
int start;
int destination;
int cnt;
int v; //该订单能获得的收益
int r; //选取该订单之后最多还能获得多少收益
}; Order orders[];
int maxE;
//记录每站有多少个乘客
int pasCnt[]; //比较函数,按start升序,destination降序,cnt降序
bool cmp(const Order &a, const Order &b) {
return a.start == b.start
? (a.destination == b.destination ? (b.cnt < a.cnt) : b.destination < a.destination)
: a.start < b.start;
} void dfs(int i, int now) {
if (now > maxE) {
maxE = now;
}
for (int t = i; t < n; ++t) {
if (orders[t].r + now <= maxE) return;
if (pasCnt[orders[t].start] + orders[t].cnt > cap) continue;//reject
for (int j = orders[t].start; j < orders[t].destination; ++j)
//get in
pasCnt[j] += orders[t].cnt;
dfs(t + , now + orders[t].v);
for (int j = orders[t].start; j < orders[t].destination; ++j)
pasCnt[j] -= orders[t].cnt;
}
} int main(void) {
while (true) {
cin >> cap >> m >> n;
if (cap == && m == && n == ) break;
for (int i = ; i < n; ++i) {
cin >> orders[i].start >> orders[i].destination >> orders[i].cnt;
orders[i].v = orders[i].cnt * (orders[i].destination - orders[i].start);
}
//按起点顺序将订单排序
sort(orders, orders + n, cmp);
for (int i = n - , sum = ; i >= ; --i) {
sum += orders[i].v;
orders[i].r = sum;
}
maxE = ;
memset(pasCnt, , sizeof(pasCnt));
dfs(, );
cout << maxE << endl;
}
return ;
}

(剪枝)

附上测试数据:


Test Input


Test Output

POJ1040 Transportation的更多相关文章

  1. poj1040 Transportation(DFS)

    题目链接 http://poj.org/problem?id=1040 题意 城市A,B之间有m+1个火车站,第一站A站的编号为0,最后一站B站的编号为m,火车最多可以乘坐n人.火车票的票价为票上终点 ...

  2. Transportation poj1040

    Ruratania is just entering capitalism and is establishing new enterprising activities in many fields ...

  3. POJ 1797 Heavy Transportation(最大生成树/最短路变形)

    传送门 Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 31882   Accept ...

  4. 【HDU 4940】Destroy Transportation system(无源无汇带上下界可行流)

    Description Tom is a commander, his task is destroying his enemy’s transportation system. Let’s repr ...

  5. Heavy Transportation(最短路 + dp)

    Heavy Transportation Time Limit:3000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64 ...

  6. POJ 1797 Heavy Transportation (Dijkstra变形)

    F - Heavy Transportation Time Limit:3000MS     Memory Limit:30000KB     64bit IO Format:%I64d & ...

  7. poj 1797 Heavy Transportation(最短路径Dijkdtra)

    Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 26968   Accepted: ...

  8. POJ 1797 Heavy Transportation

    题目链接:http://poj.org/problem?id=1797 Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K T ...

  9. uva301 - Transportation

      Transportation Ruratania is just entering capitalism and is establishing new enterprising activiti ...

随机推荐

  1. ACM学习历程—UESTC 1218 Pick The Sticks(动态规划)(2015CCPC D)

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1218 题目大意就是求n根木棒能不能放进一个容器里,乍一看像01背包,但是容器的两端可以溢出容器,只要两端的木 ...

  2. 寻找总和为n的连续子数列之算法分析

    看到有这么道算法题在博客园讨论,算法eaglet和邀月都已经设计出来了,花了点时间读了下,学到点东西顺便记录下来吧. 题目是从1...n的数列中,找出总和为n的连续子数列. 这里先设好算法中需要用到的 ...

  3. saltstack集中化管理平台

    1.安装与启动 yum install salt-master -y 安装服务端 chkconfig salt-master on 自启动 service salt-master start 启动 y ...

  4. C#中DataTable用法

    一.select方法1.筛选出男性且名字中带有李的人然后按照生日降序排列(1)DataRow[] rows=DataTable.Select("sex='"+"男&quo ...

  5. HTTP 的若干问题

    1  HTTP无状态协议和Connection:Keep-Alive容易犯的误区 HTTP无状态:无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态.从另一方面讲,打开一个服务器上的 ...

  6. 用C语言实现中文到unicode码的转换

    转自:  http://blog.csdn.net/qq_21792169/article/details/50379275 源文件用不同的编码方式编写,会导致执行结果不一样 由于本人喜欢用Notep ...

  7. ES6学习之Symbol

    定义:一种新的原始数据类型,表示独一无二的值 const a = Symbol(); const b = Symbol("foo") //接收参数的Symbol,参数表示对Symb ...

  8. Windchill 查询功能

    一.使用SearchCondition 查询语句中用容器中的containerReference.key.id名称来代替数据库中的字段idA3containerReference /**      * ...

  9. 17_点击事件第四种写法_布局文件添加onclick属性

    尽量不要用第四种点击事件的写法.在一万多行代码中发现了一个没被调用的代码 public void call(View v){//第四种写法参数一定是View v //public void call( ...

  10. CodeForces 1107F. Vasya and Endless Credits

    题目简述:给定 $n \leq 500$ 个贷款方式,其中第$i$个贷款额为$a_i$元,需要$k_i$个月偿还,每月还贷$b_i$元.在每个月月初可申请其中一个贷款,而在每个月月底时需要还贷.求:( ...