动态规划 | 背包问题 1068

 

这题对于我这种蒟蒻来说可谓是难度很大。作为pat少数的dp题,这题也有它的亮点。

①物品的价值和重量公用一个向量w

②如果最终dp[m]不等于m,说明无解

③要求结果(w序列)字典序最小

dp数组滚动示意图:

这题的标准答案是dp数组滚动。与普通无优化的背包问题不同,内循环:背包容量循环是从m(最大容量)递减到当前物品的容量。并且上个物品的dp值也是被记录在当前索引前面,起到了优化作用。

而“字典序最小”是通过① w数组递减排序②状态转移时使用<= 来实现的。普通的背包问题在转移时使用“<” 来判断,而这题进行了递减排序,字典序大的先被记录为解,如果出现了字典序小的方案,其dp值“==”上一个解的dp值,被重新记录,达到了字典序最小的效果。

下面演示“字典序最小”的工作机制:

●如果我们不进行递减排序,而是进行递增排序:

运行结果:

我们得到了字典序最大的解。

●我们进行递减排序:

 

 其本质是新解对旧解的覆盖。

AC代码(滚动优化):

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 10010
#define MAX (1<<30)-1
#define V vector<int>

using namespace std;

const int maxn=10010;//总共的钱币(相当于物品数) 
const int maxv=110;//eva的钱币(相当于重量) 
int w[maxn];
int dp[maxv];
bool choice[maxn][maxv], flag[maxn];
bool cmp(int a,int b){
    return a>b;
}

int main(){
//    freopen("I:\\pat\\动态规划\\1068_1.txt","r",stdin);
    int n,m,i,j;
    I("%d%d",&n,&m);
    for(i=1;i<=n;i++) I("%d",&w[i]);
    sort(w+1,w+1+n,cmp);    //DESC排序
    for(i=1;i<=n;i++) {            //物品循环 
        for(int v=m;v>=w[i];v--){    //背包容量递减,直到和当前物品重量相等,退出循环 
            if(dp[v]<=dp[v-w[i]]+w[i]){    //如果放入物品是更优解 
                dp[v]=dp[v-w[i]]+w[i];
                choice[i][v]=1;            //记录放入的物品 
            }else{
                choice[i][v]=0;            //记录不放入的物品 
            } 
        }
    }
    if(dp[m]!=m){
        O("No Solution");
        return 0;
    }
    int k=n,num=0,v=m;
    while(k>=0){    //从最后搜索记录结果 
        if(choice[k][v]==1){
            flag[k]=1;
            v-=w[k];
            num++;
        }
        k--;
    }
    //因为 w 数组是逆序,所以逆序输出
    for(i=n;i>=1;i--) {
        if(flag[i]){
            O("%d",w[i]);
            num--;
            if(num>0) O(" ");
        }
    }
    return 0;
}

 

posted @ 2018-03-15 09:44  TQCAI  阅读(144)  评论(0编辑  收藏  举报