动态规划训练之十三

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);
}
posted @ 2019-10-17 21:37  wzx_believer  阅读(79)  评论(0编辑  收藏  举报