dp[i][x]表示前i个工人,做x件A,最多能做多少件B。(空间可以优化成一维,但要注意for循环顺序,从大到小,向01背包那样!)
因为时间是通过二分枚举确定下来了。所以有转移方程:mid是枚举处的时间
dp[j]=max(dp[j],dp[j-k]+(mid-k*a[i])/b[i]);
代码:
#include<iostream>
#include<fstream>
using namespace std;
int n,m,mid;
int a[101],b[101];
int dp[101][101];
int solve(){
int i,j,k;
memset(dp,-1,sizeof(dp));
for(j=0;j<=m;j++)
if(mid>=j*a[1])
dp[1][j]=(mid-j*a[1])/b[1];
else
dp[1][j]=-1;
for(i=2;i<=n;i++)
for(j=0;j<=m;j++)
{
for(k=0;k*a[i]<=mid&&k<=j;k++)
if(dp[i-1][j-k]!=-1)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+(mid-k*a[i])/b[i]);
}
}
if(dp[n][m]>=m) return 1;
else return 0;
}
void read(){
// ifstream cin("in.txt");
int i,j,k;
int cas;
int maxx;
cin>>cas;
while(cas--)
{
cin>>n>>m;
maxx=0;
for(i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
maxx=max(max(maxx,a[i]),b[i]);
}
i=0;j=maxx*m*2;
while(i<=j)
{
mid=(i+j)>>1;
if(solve()) j=mid-1;
else
i=mid+1;
}
cout<<i<<endl;
}
}
int main(){
read();
return 0;
}