这是一个关于挖黄山的故事,每座黄金山都有固定需要的人手和固定的收成(不能只挖一点),在固定人数的情况下,怎样挖才能挖最多(和小偷背包装东西一样的)
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个人分别来挖的最多产量等。其中两座金山时,只需要关注第二座金山就可,关于第一座金山的最优解已经从第一个问题中解答出来了。同样的,第三座金山的时候,也只需要关注第三座金山(挖还是不挖),然后从第二个问题中得到前两座金山的最优解。