问题描述 :
有一天,他在宿舍里无意中发现了一个天平!这个天平很奇怪,有n个完好的砝码,但是没有游码。盾神为他的发现兴奋不已!于是他准备去称一称自己的东西。他准备好了m种物品去称。神奇的是,盾神一早就知道这m种物品的重量,他现在是想看看这个天平能不能称出这些物品出来。但是盾神稍微想了1秒钟以后就觉得这个问题太难了,于是就丢给了你。
注意:砝码可以和物品一起放在天平的同一边。
输入说明 :
第一行为两个数,n和m。
第二行为n个数,表示这n个砝码的重量。
第三行为m个数,表示这m个物品的重量。
1<=n<=24, 1<=m<=10.
输出说明 :
输出m行,对于第i行,如果第i个物品能被称出,输出YES否则输出NO。
输入范例 :
4 3
10 7 2 19
6 5 11
输出范例 :
NO
YES
YES
完整C++代码
每个砝码有三种情况
1:不使用这个砝码
2:将这个砝码和物品放在同一侧
3:将这个砝码放在物品另一侧
最后判断左右重量是否相等
初始代码
这下面的代码感觉很简单😂但是会超时,所以要进行优化剪枝
#include <bits/stdc++.h>
using namespace std;
int n, m, weight = 0;
int fama[30], goods[15];
int dfs(int left, int right, int num) {
if (left == right) return 1;
if (num > n) return 0;
return dfs(left + fama[num], right, num + 1) || dfs(left, right + fama[num], num + 1) || dfs(left, right, num + 1);
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> fama[i];
}
sort(fama, fama + n);
for (int i = 0; i < m; i++) {
cin >> goods[i];
}
for (int i = 0; i < m; i++) {
if (dfs(goods[i], 0, 0)) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
AC代码
#include <bits/stdc++.h>
using namespace std;
int n, m;
// 砝码重量,前i个砝码总重
int fama[30], sum[30] = {0};
bool isEqual = false;
// num表示可以用前num个砝码去称重
void dfs(int left, int right, int num) {
// 别过界、 是否符合条件、 当前差额不能大于可用砝码总和
if (num >= 1 && !isEqual && abs(left - right) <= sum[num]) {
if (abs(left - right) == fama[num]) {
isEqual = true;
} else {
// 砝码放左边,放右边,不用当前砝码
dfs(left + fama[num], right, num - 1);
dfs(left, right, num - 1);
dfs(left, right + fama[num], num - 1);
}
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> fama[i];
}
// 排序
sort(fama, fama + n);
// 前n项和
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + fama[i];
}
// 这里可以不用专门存起来,可以读一个算一个
// for (int i = 0; i < m; i++) {
// cin >> goods[i];
// }
while (m--) {
int goods;
cin >> goods;
isEqual = false;
dfs(goods, 0, n);
if (isEqual) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
😋欢迎大伙私信或者评论区交流讨论😋