poj 1973 分配任务 进阶动态规划 <难题>
2013-04-02 17:46
417 查看
题意:
软件公司有两个项目,每个项目有m个子项目,有n个程序猿,每个程序猿完成项目A或者
项目B的某一个子项目时间为x, y
每个人同一时刻只能做一个项目
项目完成时间是最晚完成的A或者B的时间,也就是说提早完成米有用
求最快完成项目需要的时间
乍一看很想背包问题,不过一时间又不清楚如何切入,把时间作为体积,每个人完成项目可以出现的次数为
每个人的分组的上限个数(即m,这样不会冲突),每个人的价值为1即完成一个部分
对于每一个时间计算是否满足要求需要,二分查找是否满足
n的上限是100,组数最大为100,需要按照分组背包优化成0-1背包问题
总之挺麻烦的,没胆切下去
看了别的解题报告,发现DP这个状态选择是一个很难也很关键的问题,如果设置为
d[i][j]表示前i个人,做j个A项目,最多可以做到B项目的个数
转移方程
d[i][j] = max { d[i][j] , d[i][j - k] + (time - A[i] * k) / B[i] }
即第i个人是做A呢还是做B呢
采用背包里面滚动数组的方法优化存储空间,时间复杂度大约在O(n * m * m)加二分,应该比一开始的想法快的多
状态如何设置是一门艺术。。
软件公司有两个项目,每个项目有m个子项目,有n个程序猿,每个程序猿完成项目A或者
项目B的某一个子项目时间为x, y
每个人同一时刻只能做一个项目
项目完成时间是最晚完成的A或者B的时间,也就是说提早完成米有用
求最快完成项目需要的时间
乍一看很想背包问题,不过一时间又不清楚如何切入,把时间作为体积,每个人完成项目可以出现的次数为
每个人的分组的上限个数(即m,这样不会冲突),每个人的价值为1即完成一个部分
对于每一个时间计算是否满足要求需要,二分查找是否满足
n的上限是100,组数最大为100,需要按照分组背包优化成0-1背包问题
总之挺麻烦的,没胆切下去
看了别的解题报告,发现DP这个状态选择是一个很难也很关键的问题,如果设置为
d[i][j]表示前i个人,做j个A项目,最多可以做到B项目的个数
转移方程
d[i][j] = max { d[i][j] , d[i][j - k] + (time - A[i] * k) / B[i] }
即第i个人是做A呢还是做B呢
采用背包里面滚动数组的方法优化存储空间,时间复杂度大约在O(n * m * m)加二分,应该比一开始的想法快的多
状态如何设置是一门艺术。。
#include <iostream> #include <vector> #include <map> #include <list> #include <set> #include <deque> #include <stack> #include <queue> #include <algorithm> #include <cmath> #include <cctype> #include <cstdio> #include <iomanip> #include <cmath> #include <cstdio> #include <iostream> #include <string> #include <sstream> #include <cstring> #include <queue> using namespace std; ///宏定义 const int INF = 990000000; const int maxn = 110 ; const int MAXN = maxn; ///全局变量 和 函数 int max(int a, int b) { return a > b ? a : b; } int T; int n, m; int A[maxn], B[maxn]; int restmax[maxn]; int maxlim; bool ok(int n, int m, int V) { int i, j, k; memset(restmax, -1, sizeof(restmax)); //初始化第一个人 for (i = 0; i <= m; i++) { if (V < i * A[i]) break; restmax[i] = max(restmax[i], (V - i * A[1]) / B[1]); } if (restmax[m] >= m) return true; //对于每一个人 for (i = 2; i <= n; i++) { //做k项A时的最大值,从大到小按照状态方程刷新状态 for (k = m; k >= 0; k--) { //遍历做0-j的所有子情况,即当前第i个人做了j个A项目 for (j = 0; j <= k; j++) { if (V < j * A[i]) break; if (restmax[k - j] != -1) { restmax[k] = max(restmax[k], restmax[k - j] + (V - j * A[i]) / B[i]); } } } if (restmax[m] >= m) return true; } return false; } int solve(int n, int m, int V) { int s, e, mid; s = 0, e = maxlim; while (s < e) { mid = (s + e) / 2; if (ok(n, m, mid)) e = mid; else s = mid + 1; } return s; } int main() { //input ///变量定义 int i, j; scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); int mm = -1; for (i = 1; i <= n; i++) { scanf("%d %d", &A[i], &B[i]); mm = max(mm, max(A[i], B[i])); } maxlim = mm * m * 2; //二分查找的上限 int ans = solve(n, m, maxlim); printf("%d\n", ans); } ///结束 return 0; }
相关文章推荐
- 一个类似auto_ptr<>用于动态分配数组的智能指针
- 动态规划之 <筷子>
- Dom4J解析xml文件动态转换为List<Bean>或者Map集合
- poj1061 青蛙的约会 && poj 2115 C Looooops<扩展欧几里得>
- 读<<IDA pro权威指南>>之动态计算目标地址
- Poj-1185 & Nyoj-81 炮兵阵地 (状态压缩动态规划经典题
- 小红的难题<递推>
- jsp 静态引入<%@ include %> 动态引入<jsp:include> 区别
- struct--timer_list <--> 定时器(动态定时器/内核定时器)
- POJ 2312<优先队列><最短路>
- ACM: 简单动态规划题 poj 2955
- linux动态调整磁盘的容量<lvm>
- POJ1014:Dividing<动归,背包问题>
- Android Wear 进阶 - 4 发送和同步数据 <Sending and Syncing Data>
- mvc 动态生成table并将tb的数据放入相应的List<T>中 (1)
- Android中ArrayList<E>动态数组用法
- ACM: 树状数组 poj 2029 动态规划…
- 100道动态规划——31 POJ 2411 && POJ 2663 && POJ 3420 状态压缩 矩阵快速幂
- POJ 2752(不满足P[i]<>P[next[i]] 的next函数)
- 扫描SD卡异步任务new AsyncTask<Integer, Integer, String>()