参考:http://www.cnblogs.com/sdjl/articles/1274312.html    感谢 作者  SDJL

问题: 金矿问题

例如:

总共100个人, 5座金矿

每一个金矿需要x人, 能产出y金. 如果不能满足x人将产出为0,挖过的人将不再挖.如何利用100人使得挖出的金矿最多

100 5  
77 92
22 22
29 87
50 46
99 90

简单分析:

1.对于每个金矿只有2种情况,挖或者不挖. 所以可以对每个金矿分2种情况讨论.将其余的金矿看成一个整体.

2.如果挖该金矿(假设此时人数足够,不够的话直接跳过这个金矿),将产出y, 人数减少x. 对剩下的人数和剩下金矿, 选中某个金矿继续分2种情况讨论

3.如果不玩我该金矿.将产出0,人数不减. 对剩下的人数和剩下金矿, 选中某个金矿继续分2种情况讨论

4.比较以上2种情况哪个更大则返回哪个

5.依次递归到最后一个金矿.判断此时人数还够不够. 就能递归回去

测试代码:

#include<iostream>
#include <fstream>
#define  max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int allp;//总人数
int allm;//总金矿数

int goals[100];//每个金矿产金量,最多100个金矿
int nump[100];//每个金矿需要的人数

int maxgoals[1000][100];//在剩下的人数基础上,剩下几个金矿最多产量.设最多1000人


void init()
{
	ifstream in("beibao0.in");
	in>>allp>>allm;
	for (int i=0;i<allm;i++)
	{
		in>>nump[i]>>goals[i];
	}
	in.close();
	for(int i=0;i<1000;i++)
	{
		for (int j=0;j<100;j++)
		{
			maxgoals[i][j]=-1;
		}
	}
}
int calcMaxGoals(int p,int m)//参数:剩下的人数和第几个金矿
{
	
	if (maxgoals[p][m]!=-1)
	{
		return maxgoals[p][m];
	}

	if (p<nump[m])
	{	
		if(m==0)
		{
			return 0;
		}
		else
		{	
			maxgoals[p][m]=calcMaxGoals(p,m-1);
			return maxgoals[p][m];
		}
		
	}
	else
	{
		if(m==0)
		{
			maxgoals[p][m]=	goals[m];
			return maxgoals[p][m];	
		}
		maxgoals[p][m]=max(calcMaxGoals(p,m-1),calcMaxGoals(p-nump[m],m-1)+goals[m]);
		return maxgoals[p][m];
	}
	
}
void main()
{
	init();
	cout<<calcMaxGoals(allp,allm-1);
	cin.get();
}