x男, y女, 限定工资(背包体积)、 求能力最大值(最大物品价值)对应的最小序列
其实分成两个背包来搞就行了,背包分别为 array[人数][工资] =》 最大值。并且记录和维护取得该最大值的最小物品序列(见注释)。
最后合并查找背包。合并背包的时候,背包1里面 { x个男的,某工资s1 => 最大价值} + 背包2里 {y个女的,某工资s2 =》最大价值} = { 工资s1+s2(<最大工资), 最大价值}。 找到这些里面最大价值和最少工资,保存满足该条件的序列们。
最后从满足条件序列中找到最小序列(排序取首个)。
#include <iostream>
#include<stack>
#include <vector>
#include <algorithm>
using namespace std;
#include <stdio.h>
int main(){
int ms,x, y,n;
cin>>n>>x>>y>>ms;cin.get();
vector<int> s(n, 0);
vector<int> b(n, 0);
vector<int> g(n, 0);
#define FEMALE 0
for(int i=0; i<n; i++){
char ss[100]; cin.getline(ss,100);
char xx; int yy, zz;
sscanf(ss, "%c %d %d", &xx, &yy, &zz);
//cout<<xx<<":"<<yy<<":"<<zz<<endl;
if(xx=='F') g[i] = FEMALE; else g[i] =1 ;
b[i] = yy, s[i] =zz;
}
{
vector<vector<int> > fb(ms+1, vector<int>(y+1, -1));
vector<vector<vector<int> > > lf (ms+1, vector<vector<int> >(y+1, vector<int> ()));
vector<vector<int> > mb(ms+1, vector<int>(x+1, -1));
vector<vector<vector<int> > > lm (ms+1, vector<vector<int> >(x+1, vector<int> ()));
fb[0][0] = mb[0][0] = 0;
for(int i=0; i<n; i++){
for(int j = ms; j>=s[i]; j--){
if(g[i] == FEMALE){
for(int k = y; k>=1; k--){
int t = fb[j-s[i]][k-1];
if(t<0) continue;
t+=b[i];
if(fb[j][k] <= t){
vector<int> tmp= lf[j-s[i]][k-1];
tmp.push_back(i);
// 更新最小物品序列lf[j][k](case 1: 找到价值更高的物品集; case 2: 找到价值相等但是排序后字典序更小的物品集 )
if(fb[j][k] < t || fb[j][k]>=0 && lf[j][k]>tmp)
lf[j][k] = tmp;
fb[j][k] = t;
}
}
}
else{
for(int k = x; k>=1; k--){
int t = mb[j-s[i]][k-1];
if(t<0) continue;
t+=b[i];
if(mb[j][k] <= t){
vector<int> tmp= lm[j-s[i]][k-1];
tmp.push_back(i);
if(mb[j][k] <t || mb[j][k]>=0 && lm[j][k]>tmp)
lm[j][k] = tmp;
mb[j][k] =t;
}
}
}
}
}
//cout<<"........."<<endl;
vector<vector<int> > res;
int mmb = 0, mms = 0;
for(int i = 0; i<=ms; i++){
for(int j = 0; j<=ms-i; j++){
int t = fb[i][y] + mb[j][x];
if(mmb<t) mmb = t, mms = i+j;
if(mmb==t) mms = min(mms, i+j);
}
}
cout<<mmb<<" "<<mms<<endl;
for(int i = 0; i<=mms; i++){
int t = fb[i][y] + mb[mms-i][x];
if(t==mmb){
vector<int> tmp = lf[i][y];
tmp.insert(tmp.end(),lm[mms-i][x].begin(), lm[mms-i][x].end());
sort(tmp.begin(), tmp.end());
res.push_back(tmp);
}
}
sort(res.begin(), res.end());
if(res.size()<=0) return 1;
//cout<<"..........."<<endl;
for(int i = 0; i<res[0].size(); i++){
cout<<res[0][i]+1<<" ";
}
cout<<endl;
}
return 0;
}