这是一个关于挖黄山的故事,每座黄金山都有固定需要的人手和固定的收成(不能只挖一点),在固定人数的情况下,怎样挖才能挖最多(和小偷背包装东西一样的)
class GoldM { public int Gold; public int People; public GoldM(int gold, int people) { Gold = gold; People = people; } } class Program { static void Main(string[] args) { //五座大金山等着你 GoldM[] goldms = new GoldM[] { new GoldM(3000,5), new GoldM(5000,6), new GoldM(2000,2), new GoldM(6000,7), new GoldM(2000,3) }; Console.WriteLine(GetMoreGold(5, 10, goldms)); Console.ReadKey(); } static int GetMoreGold(int n, int w, GoldM[] goldm) { int[] preResult = new int[w+1]; int[] result = new int[w+1]; //初始化第一行(边界),i代表人数 for (int i = 0; i <= w; i++) { if (i < goldm[0].People) { preResult[i] = 0; } else { preResult[i] = goldm[0].Gold; } } goldm[0].isVisited = true; //这里从1开始,因为初始化边界的时候0号金山已经被访问过了 for (int gg = 1; gg < n; gg++) {//金矿 for (int pp = 0; pp <= w; pp++) {//人数 if (pp < goldm[gg].People) { result[pp] = preResult[pp]; } else { //状态转移方法 int newGold = preResult[pp - goldm[gg].People] + goldm[gg].Gold; result[pp] = Math.Max(newGold, preResult[pp]); } } result.CopyTo(preResult,0);//复制数组 } return result[w]; } }
二维的动态规划,思想其实还是一样的。先划分问题,一座金山,1-n个人分别来挖的最多产量;两座金山,1-n个人分别来挖的最多产量;三座金山,1-n个人分别来挖的最多产量等。其中两座金山时,只需要关注第二座金山就可,关于第一座金山的最优解已经从第一个问题中解答出来了。同样的,第三座金山的时候,也只需要关注第三座金山(挖还是不挖),然后从第二个问题中得到前两座金山的最优解。