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];
    
  • 相关阅读:
    android WeakReference(弱引用 防止内存泄漏)与SoftReference(软引用 实现缓存机制(cache))
    android Handler.btionMessage()与Message.obtain()的区别
    android 编译
    android之xmlpullparse解析器
    android之animation
    如何用SQL语句实现Mysql数据库的备份与还原
    android之Volley实现瀑布流
    使用TCP的HelloServer
    java socket编程(网络编程)
    彻底搞懂Python切片操作
  • 原文地址:https://www.cnblogs.com/ACMerLwy/p/11268704.html
Copyright © 2011-2022 走看看