UVA_10163 Storage Keepers
感觉这个DP好暴力的。。
一开始没有想出来,后来百度了。。瞄了一眼,看到DP的记忆化搜索里面套了一个两个嵌套的for循环,才明白大概是个什么思路,原来,这里的DP用的那么暴力。
本题用了两个DP来解决。大概的思路可以再记忆化搜索的过程中体现。
还有,在输出0 0这样的数据的时候不用换行,百思不得其解。。这个还是百度出来的。
最初在写记忆化搜索的时候,漏了一个&,改了半天,买个教训,后来改的都快跟人家的一模一样了,这个最悲剧了,核心部分是对的,然后改细节。。。
下面贴代码:
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int d[101][31];//记录L的数组 6 int s[101][31];//记录工资Y的数组 7 int data[101];//记录每个人的P值 8 #define INF 1<<30 9 int maxl,m,n; 10 int dp1(int x,int y) 11 { 12 int &ans = d[x][y]; 13 if(ans != -1) 14 return ans; 15 if(x == 0) 16 { 17 ans = INF; 18 return ans; 19 } 20 if(y == 0) 21 { 22 ans = 0; 23 return ans; 24 } 25 ans = 0; 26 int i,j,temp; 27 for(i = 1;i <= y;i++) 28 { 29 temp = min(x,data[i]);//第i人最多可能看管的仓库数 30 for(j = 1;j <= temp;j++) 31 { 32 ans = max(ans,min(data[i] / j,dp1(x - j,i - 1))); 33 } 34 } 35 return ans; 36 } 37 int dp2(int x,int y) 38 { 39 int &ans = s[x][y]; 40 if(ans != -1) 41 return ans; 42 if(x == 0) 43 { 44 ans = 0; 45 return ans; 46 } 47 if(y == 0) 48 { 49 ans = INF; 50 return ans; 51 } 52 ans = INF; 53 int i,j,temp; 54 for(i = 1;i <= y;i++) 55 { 56 temp = min(x,data[i]); 57 for(j = 1;j <= temp;j++) 58 { 59 if(data[i] / j >= maxl)//这个值必须大于L的最大值 60 ans = min(ans,dp2(x - j,i - 1) + data[i]); 61 else 62 break; 63 } 64 } 65 return ans; 66 } 67 int main() 68 { 69 while(scanf("%d%d",&n,&m) != EOF) 70 { 71 if(n == 0 && m == 0) 72 break; 73 memset(d,-1,sizeof(d)); 74 memset(s,-1,sizeof(s)); 75 for(int i = 1;i <= m;i++) 76 scanf("%d",&data[i]); 77 maxl = dp1(n,m); 78 if(maxl > 0) 79 printf("%d %d\n",maxl,dp2(n,m)); 80 else 81 puts("0 0\n"); 82 }//while 83 return 0; 84 }