【DFS+剪枝+特判】 OR 【变种背包DP】
思路一(DFS):用时6ms
暴力搜索+剪枝,但要注意特判一个特殊情况
就是当所有物品的总和加起来也凑不出答案的时候
这时候会递归所有点,时间消耗最大,可能会超时
以后遇到这种一定不存在答案还要遍历所有点的情况都注意一下
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100010;
int w[N], n, m, sum;
vector<int> res;
bool has_answer, st[N];
void dfs(int u)
{
if(u == m && !has_answer)
{
for(int i = 0; i < res.size(); i ++ )
{
cout << res[i];
if(i != res.size() - 1) cout << " ";
has_answer = true;
}
return ;
}
if(has_answer) return ;
if(u > m) return ;
for(int i = 1; i <= n; i ++ )
{
if(!st[i])
{
st[i] = true;
res.push_back(w[i]);
dfs(u + w[i]);
st[i] = false;
res.pop_back();
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 1; i <= n; i ++ ) cin >> w[i];
sort(w + 1, w + n + 1);
for(int i = 1; i <= n; i ++ ) sum += w[i];
if(sum < m) //Special check!
{
puts("No Solution");
return 0;
}
dfs(0);
if(!has_answer) puts("No Solution");
return 0;
}
思路二(DP): 用时18ms
verctor保存路径
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 10010;
int n, m;
int f[N], v[N];
vector<int> res[N];
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++ ) cin >> v[i];
sort(v + 1, v + n + 1);
for(int i = 1; i <= n; i ++ )
{
for(int j = m; j >= v[i]; j -- )
{
if(f[j] < f[j - v[i]] + v[i])
{
res[j] = res[j - v[i]];
res[j].push_back(v[i]);
f[j] = f[j - v[i]] + v[i];
}
else if(f[j] == f[j - v[i]] + v[i])
{
vector<int> t = res[j - v[i]];
t.push_back(v[i]);
if(t < res[j]) res[j] = t;
}
}
}
if(f[m] == m)
{
for(int i = 0; i < res[m].size(); i ++ )
{
cout << res[m][i];
if(i != res[m].size() - 1) cout << " ";
}
}
else puts("No Solution");
return 0;
}
思路三(DP):用时30s
回溯查找路径
#include <bits/stdc++.h>
using namespace std;
int dp[10010];
int w[10010];
bool choice[10010][10010];
bool cmp(int a,int b){return a > b;}
int main() {
int n,m;
cin>>n>>m;
for(int i = 1;i <= n;i++){
cin>>w[i];
}
sort(w + 1,w + n + 1,cmp);
for(int i = 1;i <= n;i++){
for(int j = m;j >= w[i];j--){
if(dp[j] <= dp[j - w[i]] + w[i]){
choice[i][j] = true;
dp[j] = dp[j - w[i]] + w[i];
}
}
}
vector<int> res;
if(dp[m] != m) cout<<"No Solution"<<endl;
else{
int v = m, index = n;
while(v > 0) {
if(choice[index][v] == true) {
res.push_back(w[index]);
v -= w[index];
}
index--;
}
for(int i = 0;i < res.size();i++) {
if(i != 0) cout<<" ";
cout<<res[i];
}
}
return 0;
}