jzoj3515NOIP2013模拟11.6B组二分DP软件公司

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj3515NOIP2013模拟11.6B组二分DP软件公司相关的知识,希望对你有一定的参考价值。

题面

Description

一家软件开发公司有两个项目,并且这两个项目都由相同数量的m个子项目组成,对于同一个项目,每个子项目都是相互独立且工作量相当的,并且一个项目必须在m个子项目全部完成后才算整个项目完成。

这家公司有n名程序员分配给这两个项目,每个子项目必须由一名程序员一次完成,多名程序员可以同时做同一个项目中的不同子项目。

求最小的时间T使得公司能在T时间内完成两个项目。

Input

第一行两个正整数n,m(1<=n<=100,1<=m<=100)。

接下来n行,每行包含两个整数,x和y。分别表示每个程序员完成第一个项目的子程序的时间,和完成第二个项目子程序的时间。每个子程序耗时也不超过100。

Output

输出最小的时间T。

Sample Input

3 20
1 1
2 4
1 6

Sample Output

18

【样例解释】

第一个人做18个2项目,耗时18;第二个人做2个1项目,2个2项目耗时12;第三个人做18个1项目,耗时18。

Data Constraint

对于30%的数据,n<=30.
对于60%的数据,n<=60.


解题思路

首先,其实很容易想到用二分求答案,但是怎样验证二分答案呢
我在考场上用的贪心,虽然我无法证明这个贪心的正确性,但是能拿70分
贪心是错的。。。。。

考虑DP,设 f i , j f_{i,j} fi,j为前i个程序员,做j个一项目,最多可做 f i , j f_{i,j} fi,j个二项目
然后就和背包差不多,设第i个程序员做k个一项目
已知时间、做第一个项目的单个时间、做第二个项目的单个时间及做多少个一项目,那么做多少个二项目就可以求出来了
做第一个项目的单个时间 * 做多少个一项目 + 做第二个项目的单个时间 * 做多少个二项目 = 时间
(时间 - 做第一个项目的单个时间 * 做多少个一项目) / 做第二个项目的单个时间 = 做多少个二项目
f i , j = m a x ( f i , j , f i − 1 , j − k + ( m i d − a [ i ] . x ∗ k ) / a [ i ] . y ) f_{i,j}=max(f_{i,j},f_{i-1,j-k}+(mid-a[i].x * k)/a[i].y) fi,j=max(fi,j,fi1,jk+(mida[i].xk)/a[i].y)


Code

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

struct DT{
	int x, y;
}a[2000];
int n, m, l, r, mid, ans, f[1100][1100];

int check(int x) {
	memset(f, -0x7f, sizeof(f));
	for(int j = 0; j * a[1].x <= x; j++)  //预处理出一,因为前面都没有做,f为-0x7f
		f[1][j] = (x - j * a[1].x) / a[1].y;
	for(int i = 2; i <= n; i++)
		for(int j = 0; j <= m; j++)
			for(int k = 0; k * a[i].x <= x; k++)
				if(f[i - 1][j - k] >= 0)  //前面能做到j-k个一项目
					f[i][j] = max(f[i][j], f[i - 1][j - k] + (x - k * a[i].x) / a[i].y);
	if(f[n][m] >= m) return 1;
	return 0; 
}

int main() {
//	freopen("company.in", "r", stdin);
//	freopen("company.out", "w", stdout);
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++) {
		scanf("%d %d", &a[i].x, &a[i].y);
		r = max(r, a[i].x + a[i].y);
	}
	r = r * m;
	while(l <= r) {
		mid = (l + r) / 2;
		if(check(mid)) r = mid - 1, ans = mid;
			else l = mid + 1;
	}
	printf("%d", ans);
}

以上是关于jzoj3515NOIP2013模拟11.6B组二分DP软件公司的主要内容,如果未能解决你的问题,请参考以下文章

jzoj3508NOIP2013模拟11.5B组DAY 1 (7.12)HASH好元素(good)

[jzoj]3506.NOIP2013模拟11.4A组善良的精灵(fairy)(深度优先生成树)

jzoj3505NOIP2013模拟11.4A组组合逆元积木

[jzoj]3456.NOIP2013模拟联考3恭介的法则(rule)

jzoj3523NOIP2013模拟11.7A组树上倍增JIH的玩偶(tree)

jzoj3423NOIP2013模拟匈牙利Vani和Cl2捉迷藏