zoukankan      html  css  js  c++  java
  • 背包问题

    01背包

    1.记忆化搜索+dfs

    //记忆化搜索+dfs
    int rec(int i, int j) {
    	if (dp[i][j] >= 0)//已经计算过的就可以使用之前的值
    		return dp[i][j];
    	int res;
    	if (i == n)res = 0;//0-n-1,第n个当然不能放了
    	else if (j < w[i])res = rec(i + 1, j)//不能放的时候第i个最大价值等于i+1的
    	else res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
    	return dp[i][j] = res;//记忆化
    }
    

    2.dp[i][j]为从第i个物品开始挑选总重小于j时,总价值的大小

    物品从0-n-1编号

    dp[n][j]=0;

    dp[i][j]= dp[i+1][j](j< w[i])

    dp[i][j]= max(dp[i+1][j],dp[i+1][j-w[i]]+v[i])(其他)

    要求i必须先求出i+1,所以i是逆序

    for(int i=n-1;i>=0;i--)
    for (int j = 0; j <= w; 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][w] << endl;
    

    3.dp[i+1][j]:从前i个物品中选出总重量不超过j的物品时总价值的最大值

    dp[1][j]=dp[0][j]=0;

    dp[i+1][j]=dp[i][j];

    dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i])

    for (int i = 0; i < n; i++) {
    	for (int j = 0; j <= w; j++) {
    		if (j < w[i])
    			dp[i + 1][j] = dp[i][j];
    		else
    			dp[i + 1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i]);
    	}
    }
    cout << dp[n][w];
    

    4.滚动数组优化空间(常用)

    for (int i = 0; i < n; i++) {
    	for (int j = w; j >= w[i]; j--) {//逆序
    		dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
    	}
    }
    cout << dp[n] << endl;
    

    完全背包

    原理:

    dp[i+1][j]的计算中选k个的情况,与在dp[i+1][j-w[i]]中的k-1个情况完全相同,所以dp[i+1][j]可由dp[i+1][j-w[i]]的计算得到

    max{dp[i][j-kw[i]]+kv[i]|0<=k}
    =max(dp[i][j],max{dp[i][j-kw[i]]+kv[i]|k>=1})
    =max(dp[i][j],max{dp[i][j-w[i]-kw[i]]+kv[i]|k>=0}+v[i])
    =max(dp[i][j],dp[i+1][j-w[i]]+v[i])

    for (int i = 0; i < n; i++) {
    	for (int j = 0; j <= w; j++) {
    		if (j < w[i]) {
    			dp[i + 1][j] = dp[i][j];
    		}
    		else
    			dp[i + 1][j] = max(dp[i][j], dp[i + 1][j - w[i]] + v[i]);
    	}
    }
    cout << dp[n][w];
    

    滚动数组优化

    for (int i = 0; i < n; i++) {
    	for (int j = w[i]; j <= w; j++) {
    			dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
    	}
    }
    cout<<dp[w];
    
  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/ACMerLwy/p/11268704.html
Copyright © 2011-2022 走看看