nnd,记不到第一次怎么构造解的了。硬调硬搜
AC代码
#include<bits/stdc++.h>
using namespace std;
vector<int> ans, tmp, a,visited;
vector<vector<int>> prev_;
unordered_map<int,int> cache;
bool cmpLess(vector<int> & arr1, vector<int> & arr2) {
int i = 0, j = 0;
int n1 = arr1.size(), n2 = arr2.size();
if(n1 < n2)
return false;
if(n2 > n1)
return true;
while(i < n1 && j < n2 && arr1[i] == arr2[j]) {
++i;
++j;
}
if(arr1[i] < arr2[j])
return true;
return false;
}
void backtrace(int j) {
if(cache.count(j))
return;
cache[j] = 1;
if(j == 0) {
if(ans.empty() || ! cmpLess(ans, tmp))
ans = tmp;
return;
} else if(j < 0)
return;
for(auto & i : prev_[j]) {
if(visited[i])
continue;
visited[i] = 1;
tmp.push_back(a[i]);
backtrace(j - a[i]);
tmp.pop_back();
visited[i] = 0;
}
}
int main() {
int n_item, M;
cin >> n_item >> M;
a.resize(n_item);
prev_.resize(M + 1);
visited.resize(n_item);
for(int i = 0; i < n_item; ++i)
cin >> a[i];
sort(a.begin(), a.end());
vector<int> dp(M + 1, -0x3ff);
dp[0] = 0;
for(int i = 0; i < n_item; ++i) {
for(int j = M; j >= a[i]; --j) {
dp[j] = max(dp[j], a[i] + dp[j - a[i]]);
if(dp[j] < a[i] + dp[j - a[i]]) {
prev_[j] = {i};
} else if(dp[j - a[i]] + a[i] == dp[j]) {
prev_[j].push_back(i);
}
}
}
if(dp[M] != M) {
printf("No Solution\n");
return 0;
}
backtrace(M);
int len = ans.size();
for(int i = 0; i < len; ++i) {
printf("%d", ans[i]);
if(i != len - 1)
printf(" ");
}
printf("\n");
}