题目来源:网易有道2013年校园招聘面试二面试题
题目描述:

小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的。由于小明马上就要硕士毕业了,面临着买房、买车、给女友买各种包包的鸭梨,但是他的钱包却空空如也,他需要足够的money来充实钱包。万能的网友麻烦你来帮帮小明,如何在最短时间内安排自己手中的项目才能保证赚钱最多(注意:做项目的时候,项目不能并行,即两个项目之间不能有时间重叠,但是一个项目刚结束,就可以立即做另一个项目,即项目起止时间点可以重叠)。

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行是一个整数n(1<=n<=10000):代表小明手中的项目个数。
接下来共有n行,每行有3个整数st、ed、val,分别表示项目的开始、截至时间和项目的报酬,相邻两数之间用空格隔开。
st、ed、value取值均在32位有符号整数(int)的范围内,输入数据保证所有数据的value总和也在int范围内。

输出:

对应每个测试案例,输出小明可以获得的最大报酬。

样例输入:
3
1 3 6
4 8 9
2 5 16
4
1 14 10
5 20 15
15 20 8
18 22 12
样例输出:
16
22 思路:
这题初看和01背包问题类似,不同的是这里的开始和截止时间没有明确的上限,所以直接用01背包问题来做肯定是有问题的。这道题给出的上限就是项目的个数最大为10000,我们可以从这个分析,表示时间的状态最多有20000种。所以我们必须对每个项目的开始和截止时间进行离散化到0~20000之间,这样就把问题转化到01背包了。
定义dp[x],表示截止到时间x,小明可以获得的最大报酬。状态转移方程为:
  dp[x] = max{dp[x - 1], dp[l]} (l为项目的截止时间为x的开始时间)
对于离散化,可以对项目中出现的开始和截止时间存入set容器进行排序,排序后的各时间在容器中的下标就是它们的离散化值,用这些离散化值来更高对于的项目开始和截止时间就完成了对时间的离散化。
具体代码如下:
 #include <iostream>
#include <set>
#include <map>
using namespace std; typedef struct _task_t
{
int st, sd, value;
}task_t; set<int> index_map; //用于下标的离散化
map<int, int> index_map_map; //存放离散化的结果
task_t task_data[]; //存放输入数据
multimap<int, task_t *> task_map; //用于任务的映射
int dp[]; //用于dp
int n; //任务的个数
int max_proj; //任务的最大时间 #define max(a, b) (a >= b ? a : b)
int main(void)
{
int i;
pair<multimap<int, task_t *>::iterator, multimap<int, task_t *>::iterator> pos;
task_t *temp; // freopen("in.txt", "r", stdin);
while (cin >> n)
{
index_map.clear();
index_map_map.clear();
task_map.clear();
for (i = ; i <= n; i ++)
{
cin >> task_data[i].st >> task_data[i].sd >> task_data[i].value;
index_map.insert(task_data[i].st);
index_map.insert(task_data[i].sd);
}
i = ;
set<int>::iterator iterator_index = index_map.begin();
for (; iterator_index != index_map.end(); iterator_index++)
index_map_map.insert(map<int, int>::value_type(*iterator_index, i++));
max_proj = i;
for (i = ; i <= n; i ++)
{
task_data[i].st = index_map_map[task_data[i].st];
task_data[i].sd = index_map_map[task_data[i].sd];
task_map.insert(multimap<int, task_t *>::value_type(task_data[i].sd, &task_data[i]));
}
dp[] = ;
for (i = ; i < max_proj; i ++)
{
pos = task_map.equal_range(i);
dp[i] = dp[i - ];
for (; pos.first != pos.second; pos.first++)
{
temp = (pos.first)->second;
dp[i] = max(dp[i], dp[temp->st] + temp->value);
}
}
cout << dp[max_proj - ] << endl;
}
return ;
}
总结:第一次在A题的时候用C++的STL库,表示很强大!!!!

项目安排(离散化+DP)的更多相关文章

  1. nyoj720 项目安排 二分+dp

    思路:dp(i)表示前i个项目的最大收益,转移方程很好写dp(i) = max{ dp(k) + val(i) },val(i)表示第i个项目的价值,dp(k)表示前k个的最佳收益,k满足ed(k) ...

  2. 九度OJ 1499 项目安排 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1499 题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时 ...

  3. 九度oj 题目1499:项目安排

    题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的.由于小明马上就要硕士毕业了,面临着买房.买车.给 ...

  4. HDU 2836 (离散化DP+区间优化)

    Reference:http://www.cnblogs.com/wuyiqi/archive/2012/03/28/2420916.html 题目链接: http://acm.hdu.edu.cn/ ...

  5. hdu 4833 离散化+dp ****

    先离散化,然后逆着dp,求出每个点能取到的最大利益,然后看有没有钱,有钱就投 想法好复杂 #include <stdio.h> #include <string.h> #inc ...

  6. LightOJ 1085(树状数组+离散化+DP,线段树)

    All Possible Increasing Subsequences Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format: ...

  7. poj 3666 Making the Grade(离散化+dp)

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  8. EcustOJ P109跳一跳(离散化+dp)

    题目链接 感觉这道题我看了很多天,胡思乱想啊,一开始觉得记忆化搜索会可能T啊,,可能出题人的数据卡的好就稳T了的感觉..后来想了想,好像离散化一下,记一下位置之后再记忆化搜索就应该稳了吧..(好像直接 ...

  9. 【POJ3666】Making the Grade 离散化+DP

    学到了一个引理:在满足S最小化的条件下,一定存在一种构造序列B的方案,使得序列B中的数值都来自于A中.(数学归纳法+中位数定理得证) 对于状态的表示来说,首先肯定有一个 i ,表示选到了第 i 个数时 ...

随机推荐

  1. linux下 SVN切换仓库地址命令

    svn switch --relocate (Old Repository Root) (New Repository Root)

  2. angular 中父元素ng-repeat后子元素ng-click失效

    在angular中使用ng-repeat后ng-click失效,今天在这个上面踩坑了.特此记录一下. 因为ng-repeat创造了新的SCOPE.如果要使用这个scope的话就必须使用$parent来 ...

  3. iOS 添加中文支持的操作

    1.选择工程菜单,这里要选中Project,而不是Targets   2.点击Info菜单, 下拉到最后,看到Localizations. 点击+号.   3.选择中文 chinese-simplif ...

  4. Mac git提交步骤小记

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 19.0px; font: 13.0px "PingFang SC"; c ...

  5. 编译链接 C++

    预处理之后的源文件被称为一个编译单位,也即编译器的工作对象.为了使编译能够进行,程序员必须提供各种程序其他部分的声明来孤立分析一个编译单位.所有名字空间,类,函数都应该在他们所在的编译单位中有声明,所 ...

  6. 利用SQl对数据库实行数据拆分与组合

    利用SQl对数据库实行数据拆分与组合实现提供以下几种方案: 方法一: WITH CTE AS (SELECT A.Id,A.[Uid],UserName FROM (SELECT A.[id], RE ...

  7. C#_闭包陷阱

    如果匿名方法(Lambda表达式)引用了某个局部变量,编译器就会自动将该引用提升到该闭包对象中. 即将for循环中的变量i修改成了引用闭包对象的公共变量i.这样一来,即使代码执行后离开了原局部变量i的 ...

  8. 非域环境下搭建自动故障转移镜像无法将 ALTER DATABASE 命令发送到远程服务器实例的解决办法

    非域环境下搭建自动故障转移镜像无法将 ALTER DATABASE 命令发送到远程服务器实例的解决办法 环境:非域环境 因为是自动故障转移,需要加入见证,事务安全模式是,强安全FULL模式 做到最后一 ...

  9. lua中实现异步资源读写

    同样还是更新方面的需求,当我们检测到版本是新安装的以后,要进行upd目录清除.如果使用os.execute执行 rm -rf ooxx 是非常快的但由于os.execute一旦报错,那整个lua进程就 ...

  10. JavaScript常见原生DOM操作API总结

    [TOC] 最近面试的时候被这个问题给卡了,所以抽时间好好复习一下. 几种对象 Node Node是一个接口,中文叫节点,很多类型的DOM元素都是继承于它,都共享着相同的基本属性和方法.常见的Node ...