UVA10163

 1 /*
 2 
 3 题意 : M个人 看守 N个 仓库,每个人有个能力值p[i],仓库的安全值 = 能力值/看守的仓库数 ,
 4  聘请某人的花费就是他的能力值,求最高的安全值和最小花费。 
 5  
 6  两次DP,一次求最高安全值,在根据安全值求最小花费。
 7 dp[j]表示 i 个人看守j个仓库的最高安全值 
 8 */
 9 
10 #include<cstdio>
11 #include<cstring>
12 #include<algorithm>
13 using namespace std;
14 const int INF=0x3f3f3f3;
15 int dp[1010],p[50];
16 int main()
17 {
18     int n,m,ans=0;
19     while(scanf("%d%d",&n,&m)!=EOF)
20     {
21         if(!n && !m) return 0;
22         for(int i=0;i<m;i++)
23             scanf("%d",&p[i]);
24         memset(dp,0,sizeof(dp));
25         dp[0]=INF; 
26         for(int i=0;i<m;i++)        
27             for(int j=n;j>=0;j--)            
28                 for(int k=1;k<=j && k<=p[i];k++)                
29                     dp[j]=max(dp[j],min(dp[j-k],p[i]/k));  
30         ans=dp[n];
31         if(ans>0)     
32         {
33             for(int i=1;i<=n;i++) dp[i]=INF;
34             dp[0] = 0; 
35             for(int i=0;i<m;i++)
36                 for(int j=n;j>=0;j--)
37                     for(int k=min(j,p[i]/ans);k>0;k--)
38                         dp[j]=min(dp[j],dp[j-k]+p[i]);
39             printf("%d %d
",ans,dp[n])    ;            
40         }
41         else printf("0 0
");        
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/ember/p/4963044.html