uva 10163
有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; }