动态规划和贪心算法问题(应用篇)

来源:互联网 发布:华硕笔记本游戏优化 编辑:程序博客网 时间:2024/06/06 09:02

1 0-1背包问题(腾讯2014年笔试)
“背包题目”的基本描述是:有一个背包,能盛放的物品总重量为S,设有N件物品,其重量分别为w1,w2,…,wn,希望从N件物品中选择若干物品,所选物品的重量之和恰能放进该背包,即所选物品的重量之和即是S。递归和非递归解法都能求得“背包题目”的一组解,试写出“背包题目”的非递归解法。

#include<iostream>#include<string>#include<algorithm>#include<numeric>#include<fstream>using namespace std;#define MAXLEN 20#define MAXW   100void Backage(int WN[],int n,int W){ //n件物品的重量已知,选取k个恰好放进容量为W的包里,k的选择方案    bool dp[MAXLEN][MAXW];         //取k个数和为s是否存在    memset(&(dp[0][0]),0,sizeof(dp));    dp[0][0]=true;    ofstream out("1.txt");    for(int k=1;k<=n;k++){//取k个数        for(int k0=k;k0>=1;k0--){            for(int s=1;s<=W;s++){                if(s>=WN[k-1]&&dp[k0-1][s-WN[k-1]])                    dp[k0][s]=true;                out<<k0<<","<<s<<"  "<<dp[k0][s]<<endl;             }        }    }    int count=0;    for(int i=1;i<=n;i++){        if(dp[i][W]){            count++;            cout<<i<<endl;             }    }    cout<<count<<endl;  //标记选取物品的件数}int main(){    int WN[]={1,2,3,4,5,6,7};    int W=15;    Backage(WN,7,15);    system("pause");    return 0;}

网友解答如下(原理相同): 动态规划求一组解,我们用f[i][j]用来表示前i件物品随意选择一些物品能够恰好装满容量为j的背包的可行性=1,不可行则为0;如果j < v[i]:f[i][j] = f[i-1][j] ,表示第i个物品的重量已经超过最大重量j了,则结果变为了前i-1件物品能否恰好装入容量为j的背包的可行性即等于f[i-1][j];

如果j>=v[i],此时就可以选择装或者不装第i件物品了,如果装入,则它的可行性就变为了前i-1前物品是否能恰好装入j-vec[i]容量的背包中可行性了;选择不装,则它的可行性变为了前i-1物品能否恰好装入容量为j的背包中可行性了,两者有一个可行,表明前i件物品就能恰好装入容量为j的背包中。f[i][j] = f[i-1][j]||f[i-1][j-vec[i]]

初始化:f[i][0]=1(i=0,1,2,,..n) 其它的f[i][j]都等于0
找出最终的一组解,用回溯就可以了。如果存在可行解,那么f[n][S]一定为1

void packageInteration(vector<int> vec, int S){    int n = vec.size();    int **f = new int*[n+1];    for(int i = 0; i < n+1; i++){        f[i] = new int[S+1];        memset(f[i], 0, sizeof(f[i])*(S+1));    }    for(int i = 0; i < n+1; i++)        f[i][0] = 1;   // 初始化    for(int i = 1; i < n+1; i++){        for(int j = 1; j < S+1; j++){            if(j >= vec[i-1])                f[i][j] = (f[i-1][j] || f[i-1][j-vec[i-1]]);            else                 f[i][j] = f[i-1][j];        }       }    // 回溯求结果    int j = S;    for(int i = n; i > 0; i--){        if(j >= vec[i-1]){            if(f[i][j-vec[i-1]] == 1){   // 为1 表示可行                res.push_back(i);                j = j - vec[i-1];            }        }    }}
0 0