AcWing 12. 背包问题求具体方案

想出来一个(目前)不知真伪的写法
从1到n遍历,遇到当前容量(j)下价值(w)更大的方案就把path[j]清空,把path[j-v]转移过来,加上i
遇到当前容量下价值相等的方案就比较path[j-v] + i和path[j]的字典序

题解是从n到1遍历,用二维数组f[i][j]存状态
最后从1到n遍历,判断当前点(i)是否能从i+1转移过来,能选则选

题解的写法

#include<bits/stdc++.h>
using namespace std;
 
#define fr first
#define se second
 
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;
 
const int INF = 0X3f3f3f3f, N = 1000 + 10, MOD = 1e9 + 7;
 
int n,m;
int f[N];

vector<int> path[N];

bool cmp(vector<int> &x,vector<int> &y){
    for(int i=0;i<x.size() || i<y.size();i++){
        if(i>=x.size()) return true;
        if(i>=y.size()) return false;
        if(x[i] < y[i]) return true;
        if(x[i] > y[i]) return false;
    }
}
 
void work() {
    cin>>n>>m;
    
    for(int i=1;i<=n;i++){
        int v,w;
        cin>>v>>w;
        for(int j=m;j>=v;j--){
            int u=f[j-v]+w;
            if(u>f[j]){
                f[j]=u;
                path[j].clear();
                path[j]=path[j-v];
                path[j].push_back(i);
            }
            else if(u==f[j]){
                vector<int> tmp = path[j-v];
                tmp.push_back(i);
                if(cmp(tmp,path[j])) path[j] = tmp;
            }
        }
    }
    
    // cout<<f[m]<<endl;
    
    for(int i=0;i<path[m].size();i++) cout<<path[m][i]<<" ";
    
    cout<<endl;
    
}
 
signed main() {
	
	work();
	
	return 0;
}
posted @ 2022-06-28 19:18  xhy666  阅读(30)  评论(0)    收藏  举报