【二分】【DP】SOFTWARE

来源:互联网 发布:眸倾天下网络续集结局 编辑:程序博客网 时间:2024/06/06 00:18

题目链接:http://acm.upc.edu.cn/problem.php?id=2410

分析:
二分求解,DP验证。

用f[i][j]表示前i个人完成j个A任务的同时最多能完成多少B任务,f[i][j]=max(f[i-1][j-k]+x);枚举当前i完成的任务数k即可
f[i-1][j-k] 表示前i-1个人完成了j-k个A,留下k个给第i个人做。
  x=(mid-k*A[i])/B[i]  表示i在做k个A后能做多少B
  最后看f[n][m]>=m?
如果大于那么返回真,表示当前时间可行,否则返回不可行。

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;struct node{int x,y;}a[10001];int  f[101][101],n,m,md=-10000,ri,le,ans;bool dp(int ti){memset(f,-1,sizeof(f));for (int i=0;i<=n;i++) f[i][0]=0;for (int i=1;i<=n;i++) for (int j=0;j<=m;j++)  for (int k=0;k<=j;k++)   if((f[i-1][j-k]>=0) && (ti-k*a[i].x>=0))       f[i][j]=max(f[i][j],f[i-1][j-k]+(ti-k*a[i].x)/a[i].y); if(f[n][m]>=m) return true;     return false; }int main(){freopen("software.in","r",stdin);freopen("software.out","w",stdout);cin>>n>>m;for (int i=1;i<=n;i++) {     scanf("%d%d\n",&a[i].x,&a[i].y);        md=max(md,max(a[i].x,a[i].y));}ri=10000000;le=1;while (le<=ri){md=(le+ri)>>1;if(dp(md)) { ans=md; ri=md-1; }else le=md+1;}cout<<ans;return 0;}