bzoj 1569: [JSOI2008]Blue Mary的职员分配

来源:互联网 发布:奇迹归来宠物进阶数据 编辑:程序博客网 时间:2024/04/29 01:51

题意:

有n名职员,每天每名职员都可以给公司带来x单位金钱或者y单位声誉(名利不能双全),并且可以花费z单位的金钱在人才交易市场发布广告招聘职员,每次发布广告三天以后就会招聘到一名职员,并且必须在发布广告并且招聘到职员的那一天才能发布下一次广告。以最快的时间获得至少A单位金钱和至少B单位声誉。

题解:

dp
注意:这题的意思是先赚钱,再贴广告/招人。
那么就f[i][j][k]转移下就好了。
钱的上限是6*z+A。
code:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>using namespace std;int n,x,y,z,A,B,mx;int f[25][150][25];void cmin(int &x,int y){    if(x==-1) x=y;    if(y==-1) return;    x=min(x,y);}void dp(int pe,int mo,int pr){    if(pe<max(n,max(A,B))&&mo>=z)    {        int p=pe*3;        for(int i=0;i<=p;i++)            cmin(f[pe+1][min(mx,i*x+mo-z)][min(B,(p-i)*y+pr)],f[pe][mo][pr]+3);    }    for(int i=0;i<=pe;i++)        cmin(f[pe][min(mx,i*x+mo)][min(B,(pe-i)*y+pr)],f[pe][mo][pr]+1);}int main(){    scanf("%d %d %d %d %d %d",&n,&x,&y,&z,&A,&B);    memset(f,-1,sizeof(f));    mx=6*z+A;    for(int i=0;i<=n;i++) cmin(f[n][min(mx,i*x)][min(B,(n-i)*y)],1);    for(int i=n;i<=max(n,max(A,B));i++)    {        for(int j=0;j<=mx;j++)            for(int k=0;k<=B;k++)            {                if(f[i][j][k]==-1) continue;                if(j>=A&&k>=B) break;                dp(i,j,k);            }    }    int ans=-1;    for(int i=n;i<=max(n,max(A,B));i++)        for(int j=A;j<=mx;j++)        {            cmin(ans,f[i][j][B]);            //printf("%d %d %d %d\n",i,j,B,f[i][j][B]);        }    printf("%d",ans);}