編程練習:動態規劃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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章