01背包问题

1,从朴素的方法开始。。

2,第0第1,,嗯看你定义喽。。

#include<iostream>
using namespace std;
const int manx=1005;
int n,wei,w[1005],v[1005];
int rec(int i,int j)
{//从第i个物品开始挑选,同时当前可承受的重量为j 
    int res;
    if(i==n)
    {
        res=0;
    }
    else if(j<w[i])
    {
        res=rec(i+1,j);
    } 
    else 
    {
        res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
    }
    return res;
 } 
int main(){
    cin>>n;
    for(int i=0;i<n;i++){cin>>w[i];cin>>v[i];}
    cin>>wei;
    cout<<rec(0,wei);
}

3,朴素的有点像递归里面的选数。就是多了点边界条件。

if else啥的。。得拓展一下。

if(i==n){return 0;
    }
    else if(j<w[i]){res=f(i+1,j);
    }
    else{res=max(f(i+1,j),f(i+1,j-w[i])+v[i]);
    }

应该是第三个以后的选择只能用else了。应该是规范。

4,费大的话,我看题目觉得呢,有点像附加限制条件的贪心。代码呢,像有边界的选数。(核心就是啊,除了一个i==n和j<w[i]的两个边界条件,

就是一个选数,选和不选。然后用了递归的形式。和这个三个选择只能选其一的东西。

费小的话,i==n里面的条件我都改过了。

递归最后一定要返回个东西。不过好像也没啥可改的了。

 

 

 

5,至于加上记忆化的,我还是觉得我记忆化不好。

还好我记忆化弄对了/

#include<iostream>
#include<cstring>
using namespace std;
int n,wei,w[1005],v[1005];
int memo[1005][1005];
int rec(int i,int j)
{//从第i个物品开始挑选,同时当前可承受的重量为j 
    if(memo[i][j]){return memo[i][j];
    }
    if(i==n){return 0;
    }
    else if(j<w[i]){memo[i][j]=rec(i+1,j);
    } 
    else {memo[i][j]=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
    }
    return memo[i][j];
 } 
int main(){
    memset(memo,0,sizeof(memo));
    cin>>n;
    for(int i=0;i<n;i++){cin>>w[i];cin>>v[i];}
    cin>>wei;
    cout<<rec(0,wei);
}

还是比较清晰的嘿嘿。

不过我还是要分析,不,好好分析一下,我的记忆化。。

先分析时间复杂度,第一个跟选数那样的肯定是2^n了(最坏情况下)

记忆化下的分析度是nw??W??实在没有很懂。

我要好好搞一下记忆化

先看百度百科上“但是搜索到的一些解用动态规划的那种思想和模式作一些保存。”,跟动态规划????

总而言之,记忆化搜索和动态规划关系很大很大!

6,至于它这个专栏上的穷竭搜索。不就是搜索上加了个sum的状态么。。。

其他基本没变。。

7,真dp让我额。。。

#include<iostream>
using namespace std;
const int maxn=1005;
int dp[maxn][maxn];
int n,wei,w[maxn],v[maxn];
int main(){
    cin>>n;
    for(int i=0;i<n;i++){cin>>w[i];cin>>v[i];
    }
    cin>>wei;
    for(int i=n-1;i>=0;i--){
        for(int j=0;j<=wei;j++){
            if(j<w[i]){dp[i][j]=dp[i+1][j];
            }
            else {dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
            }
} } cout
<<dp[0][wei]<<endl; }

呃呃呃呃呃呃

我们来费大(感觉你之前有些浪费时间。。不过这也是为了你好理解好把》》)

费大需要用费小的模拟样例来支持。o'p'j

额,为啥从第i个物品开始挑选,总重小于j,的总价值的最大值为何

要从第i+1个算??

第三遍才完全推出来,所以你的,,结果是什么。。

我懂这个从第i个物品开始挑选是啥意思了。所以说你的代码跟你自己的状态设置关系很大。

8,上面的逆向。

定义,dp[i+1][j]为从0到i+1个物品中选出总重量不超过j的物品时总价值的最大值

递推关系式。

我........咋感觉还要推还要那啥呢。。。我突然想到了赋值的一些东西。

我突然觉得我这个掌握挺差的。。。一弄个这我就。。。。fo了。。。

9,模拟样例的时候你不能。。光写啊。。偷懒啊。。要动脑子的。

dp第一个还行,第二个就有点混乱了。

还是弄个现实的场景好想,

一个捡钻石。

未完待续。。。

posted @ 2020-01-02 14:15  北月真好  阅读(173)  评论(0编辑  收藏  举报