编程练习:动态规划0-1背包问题

原理参考此篇,写的很好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,jw1)+vi,max(m(i+1,j)),if jwiif 0j<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;
}

猜你喜欢

转载自blog.csdn.net/qiye005/article/details/52688922