题意:
有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);
}