PAT L3-001 凑零钱

01背包题目
写的时候竟然发现自己忘了怎么写01背包了,跪了
花了10分钟复习一下,发现其实还是很简单的
但这道题目要求记录轨迹,wa了好几发在轨迹上才过
dp数组可以复用,但要注意j要从小到大,确保j-w[i]用到的是i-1的数据

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5;

int n,m,k;
int w[N],dp[N],ans[N],pre[N];

int main() {
    fill(dp,dp+N,INT_MIN);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>w[i];
    sort(w+1,w+1+n);
    dp[0]=0;
    for(int i=1;i<=n;i++) {
        for(int j=m;j>=w[i];j--) {
            if(dp[j]<=dp[j-w[i]]+1) {
                dp[j]=dp[j-w[i]]+1;
                ans[j]=w[i];
                pre[j]=j-w[i];
            }
        }
    }
    if(dp[m]<=0)  cout<<"No Solution"<<endl;
    else {
        vector<int> ret;
        while(ans[m]){
            ret.push_back(ans[m]);
            m=pre[m];
        }
        for(auto it=ret.rbegin();it!=ret.rend();it++) {
            if(it!=ret.rbegin()) cout<<' ';
            cout<<*it;
        }
    }
}

posted @ 2020-02-05 12:44  潇湘风夜  阅读(119)  评论(0编辑  收藏  举报