20170801_动态规划之国王和金矿
题目: 国王和金矿
有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。
参与挖矿工人的总数是10人。
每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。
要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?
1、400金/5人 2、500金/5人 3、200金/3人 4、300金/4人 5、350金/3人
动态规划问题:maxgold[W]
N:表示金矿的数量
W:表示工人的数量
G[N]:表示每座金矿的金砖量
P[N]:表示采取每座金矿需要的工人数量
状态和状态转移方程:
1、首先设计一个表格 maxgold[W+1]
2、初始化:当只有第 1 个金矿时,工人数量 i 从 1 开始增加到 W 时,maxgold[i] 表示所能得到的最大金砖。
3、当只有第 1 个和第 2 个金矿时,工人数量 i 也同样从 1 开始增加到 W 时,
maxgold[i](已经根据状态转移方程进行修改了)表示所能得到的最大金砖。
4、依次类推,当只有第 1 个、第 2 个、第 3 个、第 4 个、第 5 个金矿时,工人数量i也同样从 1 开始增加到 W 时,
maxgold[i](已经根据状态转移方程进行修改了)表示所能得到的最大金砖。
5、时间复杂度:O( N * W )
空间复杂度:O( W )
//国王与金矿
/*
题目一:上楼梯有多少种走法
题目二: 国王和金矿
有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。
参与挖矿工人的总数是10人。
每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。
要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?
1、400金/5人 2、500金/5人 3、200金/3人 4、300金/4人 5、350金/3人
*/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/*
动态规划问题:maxgold[W]
1、首先设计一个表格maxgold[W+1]
2、初始化:当只有第1个金矿时,工人数量i从1开始增加到W时,maxgold[i]表示所能得到的最大金砖。
3、当只有第1个和第2个金矿时,工人数量i也同样从1开始增加到W时,
maxgold[i](已经根据状态转移方程进行修改了)表示所能得到的最大金砖。
4、依次类推,当只有第1个、第2个、第3个、第4个、第5个金矿时,工人数量i也同样从1开始增加到W时,
maxgold[i](已经根据状态转移方程进行修改了)表示所能得到的最大金砖。
5、时间复杂度:O( N * W )
空间复杂度:O( W )
*/
int GetMaxGold(int N, int W, const vector<int> &G, const vector<int> &P)
{
vector<int> premaxgold(W+1,0); //设计一个结果表的前表
vector<int> maxgold(W+1,0); //设计一个结果表
for(int i=1; i<=W; ++i) //按列 初始化结果表:当只有第一座金矿时,i代表i个工人
{
if(i<P[0])
premaxgold[i]=0;
else
premaxgold[i]=G[0];
}
//依次填充表格
for(int i=0; i<N; ++i) //i表示有前i个金矿时
{
for(int j=1; j<=W; ++j)
{
if(j<P[i])
maxgold[j]=premaxgold[j];
else
maxgold[j]=max(premaxgold[j], premaxgold[j-P[i]]+G[i]);
}
premaxgold=maxgold;
}
return maxgold[W];
}
int main(void)
{
int N=5; //5个金矿
int W=10; //10个人:900
//int W=13; //13个人:1250
//int W=1; //1个人:0
//int W=3; //3个人:350
//int W=7; //7个人:650
int g[]={400,500,200,300,350};
vector<int> G(begin(g),end(g)); //每座金矿的含金量
int p[]={5,5,3,4,3};
vector<int> P(begin(p),end(p)); //每座金矿需要的人数
int maxGold=GetMaxGold(N,W,G,P);
cout<<maxGold<<endl;
system("pause");
return 0;
}