POJ1040 Transportation
题目来源: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的更多相关文章
- poj1040 Transportation(DFS)
题目链接 http://poj.org/problem?id=1040 题意 城市A,B之间有m+1个火车站,第一站A站的编号为0,最后一站B站的编号为m,火车最多可以乘坐n人.火车票的票价为票上终点 ...
- Transportation poj1040
Ruratania is just entering capitalism and is establishing new enterprising activities in many fields ...
- POJ 1797 Heavy Transportation(最大生成树/最短路变形)
传送门 Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 31882 Accept ...
- 【HDU 4940】Destroy Transportation system(无源无汇带上下界可行流)
Description Tom is a commander, his task is destroying his enemy’s transportation system. Let’s repr ...
- Heavy Transportation(最短路 + dp)
Heavy Transportation Time Limit:3000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64 ...
- POJ 1797 Heavy Transportation (Dijkstra变形)
F - Heavy Transportation Time Limit:3000MS Memory Limit:30000KB 64bit IO Format:%I64d & ...
- poj 1797 Heavy Transportation(最短路径Dijkdtra)
Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 26968 Accepted: ...
- POJ 1797 Heavy Transportation
题目链接:http://poj.org/problem?id=1797 Heavy Transportation Time Limit: 3000MS Memory Limit: 30000K T ...
- uva301 - Transportation
Transportation Ruratania is just entering capitalism and is establishing new enterprising activiti ...
随机推荐
- Arc082_F Sandglass
Description有一个沙漏由两个上下相通玻璃球$A$和$B$构成,这两个玻璃球都含有一定量的沙子,我们暂且假定$A,B$中位于上方的玻璃球的为$U$,下方的玻璃球为$L$,则除非$U$中没有沙子 ...
- BZOJ4545: DQS的trie
BZOJ4545: DQS的trie https://lydsy.com/JudgeOnline/problem.php?id=4545 分析: 对trie用dfs建sam复杂度是\(O(n^2)\) ...
- poj3585 Accumulation Degree[树形DP换根]
思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...
- POJ 1503 Integer Inquiry(大数相加)
一.Description One of the first users of BIT's new supercomputer was Chip Diller. He extended his exp ...
- Poj1218_THE DRUNK JAILER(水题)
一.Description A certain prison contains a long hall of n cells, each right next to each other. Each ...
- bean validator - Hibernate validator
在后台开发过程中,对参数的校验成为开发环境不可缺少的一个环节.比如参数不能为null,email那么必须符合email的格式,如果手动进行if判断或者写正则表达式判断无意开发效率太慢,在时间.成本.质 ...
- J2EE 学习路线
分享一个比较好的学习网站 http://edu.51cto.com/roadmap/view/id-86.html ================================J2EE=== ...
- mkfs在特定的分区上建立 linux 文件系统
Linux mkfs命令用于在特定的分区上建立 linux 文件系统 使用方式 : mkfs [-V] [-t fstype] [fs-options] filesys [blocks]参数 : ...
- 第2天视频 08_androidHelloworld
为什么应用的包名要用公司域名倒写呢?如何区分不同的安卓应用?高版本的应用装了之后会把低版本的应用覆盖掉.如果是不同的应用跟其他应用没关系只要装上去就可以了.区别不同的应用用的比较关键的东西是一个是应用 ...
- [codeforces821E]Okabe and El Psy Kongroo
题意:(0,0)走到(k,0),每一部分有一条线段作为上界,求方案数. 解题关键:dp+矩阵快速幂,盗个图,注意ll 关于那条语句为什么不加也可以,因为我的矩阵C,就是因为多传了了len的原因,其他位 ...