poj1040 Transportation(DFS)
题目链接
http://poj.org/problem?id=1040
题意
城市A,B之间有m+1个火车站,第一站A站的编号为0,最后一站B站的编号为m,火车最多可以乘坐n人。火车票的票价为票上终点站的编号减去起点站的编号。输入火车票订单的数目orderNums,接着输入orderNums个订单,每个订单由3个数字s,e,p组成,分别表示订单的起点站,终点站,该订单的人数,必须全部接受订单上的乘客或者全部不接受,求铁路公司最多可以赚多少钱。
思路
对于一个订单来说,有两种情况:接受和不接受。我们只需将所有可能的情况枚举出来,然后求在每一种情况下,铁路公司所赚的钱的最大值即可,这种枚举很适合使用dfs来解决。为了简化求解,我们要保证乘客是按火车站的编号顺序来上车,所以要将订单按订单起点的编号从低到高排序,若起点相同,则按终点编号从低到高排序。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std; struct Order
{
int s; //起点
int e; //终点
int p; //人数 Order(int s, int e, int p):s(s), e(e), p(p){}
}; bool cmp(Order o1, Order o2) //将订单排序
{
if(o1.s==o2.s)
return o1.e<o2.e;
return o1.s<o2.s;
} const int N = ;
vector<Order> orders;
int n, m, orderNums;
int down[N]; //down[i]表示第i站下车的人数
int ans; /*
* p : 当前车上的人数
* cur : 当前处理第cur个订单
* sum : 当前赚的钱数
*/
void dfs(int p, int cur, int sum)
{
if(cur==orderNums)
{
ans = max(ans, sum);
return;
} if(cur>) //减去上一个订单的下车人数
{
for(int i=orders[cur-].s+; i<=orders[cur].s; i++)
p-=down[i]; //减去下车的人数
}
if(p+orders[cur].p <= n)
{
down[orders[cur].e] += orders[cur].p;
dfs(p+orders[cur].p, cur+, sum + (orders[cur].e-orders[cur].s)*orders[cur].p);
down[orders[cur].e] -= orders[cur].p; //注意恢复现场,便于回溯
}
dfs(p, cur+, sum);
} int main()
{
//freopen("poj1040.txt", "r", stdin);
while(cin>>n>>m>>orderNums && n)
{
ans = -;
orders.clear();
memset(down, , sizeof(down));
for(int i=; i<orderNums; i++)
{
int s, e, p;
cin>>s>>e>>p;
orders.push_back(Order(s, e, p));
} sort(orders.begin(), orders.end(), cmp);
dfs(, , );
cout<<ans<<endl;
}
return ;
}
一点思考
除了上面代码中的dfs写法,还可以换一种dfs写法,思路是在循环遍历订单时进行dfs,我感觉这种方法比上一种dfs方法要容易想一点,但实现起来比上一种要麻烦一些。代码和上面的代码基本一样,只是dfs函数有所不同。代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std; struct Order
{
int s; //起点
int e; //终点
int p; //人数 Order(int s, int e, int p) :s(s), e(e), p(p) {}
}; bool cmp(Order o1, Order o2) //将订单排序
{
if (o1.s == o2.s)
return o1.e<o2.e;
return o1.s<o2.s;
} const int N = ;
vector<Order> orders;
int n, m, orderNums;
int down[N]; //down[i]表示第i站下车的人数
int ans; /*
* p : 当前车上的人数
* pre : 当前处理订单的上一个接受订单
* cur : 当前处理第cur个订单
* sum : 当前赚的钱数
*/
void dfs(int p, int pre, int cur, int sum)
{
if (cur> && cur<orderNums) //减去上一个订单的下车人数
{
for (int i = orders[pre].s + ; i <= orders[cur].s; i++)
p -= down[i]; //减去下车的人数
}
for (int i = cur; i<orderNums; i++)
{
bool flag = false;
for (int j = orders[cur].s + ; j <= orders[i].s; j++) //测试是否能接受订单i
{
p -= down[j]; //减去下车的人数 (位置1)
flag = true;
}
if (p + orders[i].p <= n)
{
pre = i;
down[orders[i].e] += orders[i].p;
dfs(p + orders[i].p, pre, i + , sum + (orders[i].e - orders[i].s)*orders[i].p);
down[orders[i].e] -= orders[i].p; //注意恢复现场,便于回溯
}
if (flag) //只有在位置1减了的情况下再加回来
{
for (int j = orders[cur].s + ; j <= orders[i].s; j++)
p += down[j]; //加上位置1减去的人数,恢复现场,便于回溯
}
}
ans = max(ans, sum);
} int main()
{
//freopen("poj1040.txt", "r", stdin);
while (cin >> n >> m >> orderNums && n)
{
ans = -;
orders.clear();
memset(down, , sizeof(down));
for (int i = ; i<orderNums; i++)
{
int s, e, p;
cin >> s >> e >> p;
orders.push_back(Order(s, e, p));
} sort(orders.begin(), orders.end(), cmp);
dfs(, , , );
cout << ans << endl;
}
return ;
}
这份代码提交后内存占用与第一份代码相同,时间上稍微慢了一点点。
poj1040 Transportation(DFS)的更多相关文章
- LeetCode Subsets II (DFS)
题意: 给一个集合,有n个可能相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: 看这个就差不多了.LEETCODE SUBSETS (DFS) class Solution { publ ...
- LeetCode Subsets (DFS)
题意: 给一个集合,有n个互不相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: DFS方法:由于集合中的元素是不可能出现相同的,所以不用解决相同的元素而导致重复统计. class Sol ...
- HDU 2553 N皇后问题(dfs)
N皇后问题 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Description 在 ...
- 深搜(DFS)广搜(BFS)详解
图的深搜与广搜 一.介绍: p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: justify; orp ...
- 【算法导论】图的深度优先搜索遍历(DFS)
关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...
- 深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现
1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...
- 深度优先搜索(DFS)和广度优先搜索(BFS)
深度优先搜索(DFS) 广度优先搜索(BFS) 1.介绍 广度优先搜索(BFS)是图的另一种遍历方式,与DFS相对,是以广度优先进行搜索.简言之就是先访问图的顶点,然后广度优先访问其邻接点,然后再依次 ...
- 图的 储存 深度优先(DFS)广度优先(BFS)遍历
图遍历的概念: 从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础.图的 ...
- 搜索——深度优先搜索(DFS)
设想我们现在身处一个巨大的迷宫中,我们只能自己想办法走出去,下面是一种看上去很盲目但实际上会很有效的方法. 以当前所在位置为起点,沿着一条路向前走,当碰到岔道口时,选择其中一个岔路前进.如果选择的这个 ...
随机推荐
- 多重检验_LSD方法不准确性
sklearn实战-乳腺癌细胞数据挖掘(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005269003&a ...
- Installing kubectl
Installing kubectl Kubernetes uses a command-line utility called kubectl for communicating with the ...
- JAVA Remote Object
RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象相互调用实现双方通讯的一种通讯机制.使用这种机制,某一台计算机上的对象可以调用另一台计算机上的对象来获 ...
- [SDOI2005]区间
题目描述 现给定n个闭区间[ai, bi],1<=i<=n.这些区间的并可以表示为一些不相交的闭区间的并.你的任务就是在这些表示方式中找出包含最少区间的方案.你的输出应该按照区间的升序排列 ...
- CF766 ABCDE
LINK A 找最长非公共子序列..如果两串不是完全相同 显然就是最长的那个 /** @Date : 2017-04-15 19:52:34 * @FileName: 766A.cpp * @Plat ...
- Javascript正则表达式难点、重点
重复的贪婪性 {n,m} {n,} {n} ? + * ?表示匹配0次或1次,(最多匹配1次): +表示匹配1次或多次,(最少匹配1次): *表示匹配0次或多次,(匹配任意次): {m,n}表示匹配m ...
- asp.net core 实践
github:https://github.com/zzhi/DotNetWeb 这是一个基于asp.net core web application的练习项目,目的是学习dotnet core新技能 ...
- asp.net后台代码动态添加JS文件和css文件的引用
首先添加命名空间 using System.Web.UI.HtmlControls; 代码动态添加css文件的引用 HtmlGenericControl myCss = new HtmlGeneric ...
- hdfs的datanode工作原理
datanode的作用: (1)提供真实文件数据的存储服务. (2)文件块(block):最基本的存储单位.对于文件内容而言,一个文件的长度大小是size,那么从文件的0偏移开始,按照固定的大小,顺序 ...
- lspci 虚拟机网卡对应关系
我这个办法有点笨: 到 /sys/devices/ 下去搜索网卡 eth*,找到网卡对应的PCI 总线位置,例如:05:00.0. 然后通过 "lspci -s 05:00.0" ...