zoukankan      html  css  js  c++  java
  • C++动态规划求解0-1背包问题

    问题描述:

    给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问:应该如何选择装入背包的物品,是的装入背包中物品的总价值最大?

    细节须知:

    暂无。

    算法原理:

    a.最优子结构性质

    0-1背包问题具有最优子结构性质。设(y1,y2,…,yn)是所给0-1背包问题的一个最优解,则(y2,…,yn)是下面相应子问题的一个最优解。

    b.递归关系

    设所给0-1背包问题的子问题

    的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。有0-1背包问题的最优子结构性质,可以建立如下计算m(i,j)的递归式

        

      1 #include <iostream>
      2 #include <fstream>
      3 #include <ctime>
      4 #include <algorithm>
      5 #include <windows.h>
      6 using namespace std;
      7 #define N 10000
      8 
      9 //int w[5] = { 0 , 2 , 3 , 4 , 5 };            //商品的体积2、3、4、5
     10 //int v[5] = { 0 , 3 , 4 , 5 , 6 };            //商品的价值3、4、5、6
     11 //int bagV = 8;                            //背包大小
     12 int dp[N][N];                    //动态规划表
     13 //int item[5];                            //最优解情况
     14 
     15 void findMax(int k,int n,int w[],int v[]) {                    //动态规划
     16     for (int i = 1; i <= k; i++) {
     17         for (int j = 1; j <= n; j++) {
     18             if (j < w[i])
     19                 dp[i][j] = dp[i - 1][j];
     20             else
     21                 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
     22         }
     23     }
     24 }
     25 
     26 void findWhat(int i, int j,int w[],int v[],int item[]) {                //最优解情况
     27     if (i > 0) {
     28         if (dp[i][j] == dp[i - 1][j]) {
     29             item[i] = 0;
     30             findWhat(i - 1, j,w,v,item);
     31         }
     32         else if (j - w[i] >= 0 && dp[i][j] == dp[i - 1][j - w[i]] + v[i]) {
     33             item[i] = 1;
     34             findWhat(i - 1, j - w[i],w,v,item);
     35         }
     36     }
     37 }
     38 
     39 void print(int k,int n,int item[]) {
     40     /*for (int i = 0; i < k+1; i++) {            //动态规划表输出
     41         for (int j = 0; j < n+1; j++) {
     42             cout << dp[i][j] << ' ';
     43         }
     44         cout << endl;
     45     }
     46     cout << endl;*/
     47     cout <<"The item number that should be put into the backpack is:";
     48     for (int i = 0; i < k+1; i++){            //最优解输出
     49         if(item[i] == 1)
     50           cout << i << ' ';
     51     }
     52     cout << endl;
     53 }
     54 
     55 int main(void)
     56 {
     57     LARGE_INTEGER nFreq;
     58     LARGE_INTEGER nBeginTime;
     59     LARGE_INTEGER nEndTime;
     60     ofstream fout;
     61     double cost;
     62     int i,j,m,n,k;
     63     cout << "Please enter the number of times you want to run the program:";
     64     cin >> m;
     65     //int object_amount[m];
     66     //double runtime[m];
     67     fout.open("backpack.txt",ios::app);
     68     if(!fout){
     69         cerr<<"Can not open file 'backpack.txt' "<<endl;
     70         return -1;
     71     }
     72     fout.setf(ios_base::fixed,ios_base::floatfield);       //防止输出的数字使用科学计数法
     73     srand((unsigned int)time(NULL));
     74     for(i = 0; i < m; i++){
     75         n = rand()%10000;
     76         k = rand()%10000;
     77         //object_amount[i] = k;
     78         fout<<k<<",";
     79         int item[k];
     80         cout << "The " << i+1 << "th test's backpack lattice number is:" << n << endl;
     81         cout << "The " << i+1 << "th test's object amount is:" << k << endl;
     82         int w[k];
     83         int v[k];
     84         memset(dp,0,sizeof(dp));
     85         w[0] = 0;
     86         v[0] = 0;
     87         for(j=1;j<k;j++){
     88             w[j]=rand()%100;
     89             v[j]=rand()%1000;
     90         }
     91         QueryPerformanceFrequency(&nFreq);
     92         QueryPerformanceCounter(&nBeginTime);
     93         findMax(k,n,w,v);
     94         findWhat(k,n,w,v,item);
     95         print(k,n,item);
     96         QueryPerformanceCounter(&nEndTime);
     97         cost=(double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart;
     98         //runtime[i]=cost;
     99         fout<<cost<<endl;
    100         cout<<"The running time is:"<<cost<<" s"<<endl;
    101     }
    102 /*    fout.open("backpack.txt",ios::app);
    103     if(!fout){
    104         cerr<<"Can not open file 'backpack.txt' "<<endl;
    105         return -1;
    106     }
    107     fout.setf(ios_base::fixed,ios_base::floatfield);       //防止输出的数字使用科学计数法
    108     for(i=0;i<m;i++){
    109            fout<<object_amount[i]<<","<<runtime[i]<<endl;
    110     }*/
    111     fout.close();
    112     cout<<"Success!"<<endl;
    113     return 0;
    114 }

    程序设计思路:

    根据算法原理中所述递归关系,递归计算全部的m(i,j),得到不同情况下的最优解。

    假设m[1][c]给出所要求的的0-1背包问题的最优值。相应的最优解计算如下:

    如果m[1][c]=m[2][c],则x1=0;否则x1=1.当x1=0是,由m[2][c]继续构造最优解;当x1=1时,有m[2][c-w1]继续构造最优解。以此类推,可构造出相应的最优解(x1,x2,…,xn)。

    时间复杂性分析:

    从计算m(i,j)的递归式容易看出,对于0-1背包问题的求解算法需要O(nc)计算时间,而算法解出最优方案需要O(n)计算时间,当背包容量c很大时,算法需要的计算时间较多。

    生成的数据可导入EXCEL中进行数据分析生成分析图表。

  • 相关阅读:
    线段树小结
    线段树 区间合并
    线段树
    线段树离散化+区间修改
    线段树模板

    geatpy
    基于Anaconda 安装 geatpy 和 tensorflow
    Python 求“元组、列表、字典、数组和矩阵”的大小
    np.array()和np.mat()区别
  • 原文地址:https://www.cnblogs.com/Jesse-Cavendish/p/11771656.html
Copyright © 2011-2022 走看看