动态规划训练之十三
https://www.luogu.org/problem/P1800
开始还在纠结到底把这道题归为二分还是dp
但发现这道题难点在于dp
根据样例解释会很好想到要用二分
只是这个check函数就比较尴尬了
肯定贪心扫不出来,说明就只有dp了啊
而且这个dp要和你二分出来的答案有关
dp[i,j]表示第i个人完成1模块的j块,大家还可以完成2模块的最多模块数
#include<iostream>
#include<cstdio>
using namespace std;
int f[101][101];//第i个人完成1模块的j块,大家还可以完成2模块的最多模块数
int d[101][2]/*i是人,1,2是模块,存效率*/,l,mid,r,n,m,t;
int main()
{
//freopen("software.in","r",stdin);
//freopen("software.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&d[i][0],&d[i][1]);
r=10000;
while (l<r) //二分枚举天数;
{
mid=(l+r)/2;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
f[i][j]=-9999999;
f[0][0]=0;
for(int i=1;i<=n;i++) //枚举人;
for(int j=0;j<=m;j++) //枚举模块;
for(int k=0;k<=min(j,mid/d[i][0])/*第i个人mid天最多完成1模块数*/;k++)//枚举第i个人做几个1模块;
f[i][j]=max(f[i][j],f[i-1][j-k]+(mid-d[i][0]*k)/d[i][1]);
if (f[n][m]>=m)//如果可以完成的多;
r=mid;//短几天;
else
l=mid+1;//长一天;
}
printf("%d",l);
}