有N个仓库,总共有M个人来应聘仓库看守员,每个人的能力是P,一个人可以看守多个仓库(设k个),每个仓库只能被一个人看,仓库的安全系数为p/k,公司的安全底线为最低的仓库安全系数,每个人每月的薪水是P,求能使安全底线最高的值和达到此值中最小的花费。
有两个条件,最低线和花费,要加一维开三维的数组,把每个人看1到n个仓库分作w为p,c为p/k的物品, dp[i][j][k]中i为第i组,总共有j个仓库时,安全线大等于k时的最小花费
#include<stdio.h>
#include<string.h>
#define INF 1<<30
int dp[2][110][1010];
int c[33][110];
int w[33];
int n,m;
int min(int a,int b)
{
return a>b?b:a;
}
int main()
{
int i,j,k,l,p,t,pmax;
while(~scanf("%d %d",&n,&m)&&n+m!=0)
{
pmax=-1;
for(i=0;i<m;i++)
{
scanf("%d",&p);
if(pmax<p)
pmax=p;
c[i][0]=0;
w[i]=p;
for(j=1;j<=n;j++)
{
c[i][j]=p/j;
}
}
for(i=0;i<2;i++)
{
for(k=0;k<=pmax;k++)
dp[i][0][k]=0;
for(j=1;j<=n;j++)
{
for(k=0;k<=pmax;k++)
dp[i][j][k]=INF;
}
}
for(i=0;i<m;i++) //人
{
memcpy(dp[i%2],dp[(i+1)%2],sizeof(dp[0]));
for(j=1;j<=n&&c[i][j];j++) //当前看几个仓库
{
for(t=j;t<=n;t++) //可以放的状态的仓库数
{
for(k=1;k<=c[i][j];k++) //可以放的安全系数比它小,不改变当前k值
{
if(dp[(i+1)%2][t-j][k]!=INF)
dp[i%2][t][k]=min(dp[i%2][t][k],dp[(i+1)%2][t-j][k]+w[i]);
}
}
}
}
int flag=0;
for(i=pmax;i>=0;i--)
{
if(dp[(m-1)%2][n][i]!=INF)
{
printf("%d %d\n",i,dp[(m-1)%2][n][i]);
flag=1;
break;
}
}
if(flag==0)
printf("0 0\n");
}
return 0;
}