原理参考此篇,写的很好http://blog.csdn.net/dapengbusi/article/details/7463968
- 动态规划0-1背包问题
Ø
问题描述:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装
入背包中物品的总价值最大?
Ø
对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态可以取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。
过程分析
数据:物品个数n=5,物品重量w[n]={0,2,2,6,5,4},物品价值V[n]={0,6,3,5,4,6},
(第0位,置为0,不参与计算,只是便于与后面的下标进行统一,无特别用处,也可不这么处理。)总重量c=10.
Ø背包的最大容量为10,那么在设置数组m大小时,可以设行列值为6和11,那么,对于m(i,j)就表示可选物品为i…n背包容量为j(总重量)时背包中所放物品的最大价值。
接下来是在笔试中遇到的问题,首先应根据题意归结出是什么问题,在根据相应的基本问题解法做相应修改即可。
- 问题描述
炉石游戏单张卡牌有卡牌消耗水晶和伤害,给定水晶上限和卡牌数量,并输入卡牌尺寸,求最大伤害。
关键地推公式为:
f(n)=⎧⎩⎨maxm(i+1,j),m(i+1,j−w1)+vi,max(m(i+1,j)),if j≤wiif 0≤j<wi
#include<iostream>
#include<vector>
#include<algorithm>
#include<exception>
using namespace std;
//函数定义
//模板类matrix头文件定义
template<class T>
class matrix
{
public:
matrix(int rows = 1, int cols = 1, const T&value = T()); //构造函数
vector<T>&operator[](int i); //提领运算
const vector<T>&operator[](int i)const; //提领预算
int rows()const{ return row; } //矩阵行数
int cols()const{ return col; } //矩阵列数
void resize(int rows, int cols); //重置矩阵大小
void print_matrix(ostream&out)const; //矩阵输出
private:
int row, col; //矩阵行数和列数
vector<vector<T>>mat; //向量表示的矩阵
};
//定义自己的异常
class MyMatIndUnboundException :public exception
{
virtual const char* what() const throw()
{
return "matrix index cross boarder!";
}
}myExcept;
//子函数实现功能
//构造函数
template<class T>
matrix<T>::matrix(int rows, int cols, const T& value) :row(rows), col(cols), mat(rows, vector<T>(cols, value))
{
}
//提领函数
template<class T>
vector<T>& matrix<T>::operator[](int i)
{
if (i < 0 || i >= row)throw myExcept;
return mat[i];
}
template<class T>
const vector<T>& matrix<T>::operator[](int i) const
{
if (i < 0 || i >= row)throw myExcept;
return mat[i];
}
//重置矩阵大小
template<class T>
void matrix<T>::resize(int rows, int cols)
{
if (rows == row&&cols == col)
return;
row = rows, col = cols;
mat.resize(row); //重置行数
for (int i = 0; i < row; i++)
mat[i].resize(col); //重置列数
}
//打印矩阵元素
template<class T>
void matrix<T>::print_matrix(ostream&out)const
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
int main()
{
//定义消耗水晶数和卡牌数量
int N, M; //N为水晶数
cin >> N >> M;
vector<int> cardConsu;
cardConsu.push_back(0);
vector<int> damage;
damage.push_back(0);
//输入卡牌身材
int singleCardConSu;
int singleCardDam;
while (cin >> singleCardConSu >> singleCardDam)
{
cardConsu.push_back(singleCardConSu);
damage.push_back(singleCardDam);
}
matrix<int> Mat(M + 1, N + 1, 0);
int i = 1;
int j = 1;
for (i = 1; i <= M; i++)
{
for (j = 1; j <= N; j++)
{
// 递推关系式出炉
if (j < cardConsu[i])
{
Mat[i][j] = Mat[i - 1][j];
}
else
{
int x = Mat[i - 1][j];
int y = Mat[i - 1][j - cardConsu[i]] + damage[i];
Mat[i][j] = x < y ? y : x;
}
}
}
Mat.print_matrix(cout);
int max = 0;
for (int i = 0; i <M+1; i++)
{
for (int j = 0; j <N+1; j++)
{
if (Mat[i][j] > max)
max = Mat[i][j];
}
}
cout << max<<endl;
return 0;
}