题解:P15051 [UOI 2023 II Stage] Nova Poshta
题目主要意思
给定
思路
先算货物总重,判断单辆卡车能否单独装下并输出对应结果;若不能,二进制枚举所有分给Vasyl的货物组合,验证合法则输出合作方案,无合法组合则输出无法完成。
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 存储5件货物的重量,下标0-4对应货物1-5
vector<int> w(5);
int M1, M2, sum = 0; // M1/Vasyl卡车容量 M2/Petro卡车容量 sum/货物总重量
// 输入5件货物重量并累加总重
for (int i = 0; i < 5; i++) {
cin >> w[i];
sum += w[i];
}
// 输入两辆卡车的载重量
cin >> M1 >> M2;
// 判断单辆卡车是否能单独装下所有货物
bool vasyl_alone = (sum <= M1); // Vasyl单独运输是否可行
bool petro_alone = (sum <= M2); // Petro单独运输是否可行
if (vasyl_alone && petro_alone) { // 两人都能单独运输
cout << "They both can do it!" << endl;
return 0;
}
if (vasyl_alone) { // 仅Vasyl能单独运输
cout << "Vasyl can do it!" << endl;
return 0;
}
if (petro_alone) { // 仅Petro能单独运输
cout << "Petro can do it!" << endl;
return 0;
}
// 存储最终分配方案:Vasyl和Petro分别装的货物编号
vector<int> vas, pet;
bool find_sol = false; // 标记是否找到合法分配方案
// 二进制枚举Vasyl的货物组合,mask从1到31(5位二进制,覆盖所有非空组合)
for (int mask = 1; mask < (1 << 5); mask++) {
int sum_vas = 0; // 当前组合中Vasyl装载的货物总重
vector<int> tmp_vas; // 临时存储当前组合的货物编号
for (int i = 0; i < 5; i++) {
// 若mask的第i位为1,说明第i+1号货物分给Vasyl
if (mask & (1 << i)) {
sum_vas += w[i];
tmp_vas.push_back(i + 1);
}
}
int sum_pet = sum - sum_vas; // Petro装载的剩余货物总重
// 验证当前分配是否合法:两人的装载重量都不超过各自卡车容量
if (sum_vas <= M1 && sum_pet <= M2) {
vas = tmp_vas; // 保存Vasyl的货物分配
// 遍历所有货物,将未分给Vasyl的分给Petro
for (int i = 0; i < 5; i++) {
if (!(mask & (1 << i))) {
pet.push_back(i + 1);
}
}
find_sol = true; // 找到合法方案
break; // 找到即退出,无需继续枚举
}
}
// 根据是否找到合法方案输出结果
if (!find_sol) { // 无合法方案,无法完成配送
cout << "They can not do it!" << endl;
} else { // 找到合法方案,输出合作结果及分配
cout << "They need to work together!" << endl;
cout << "Vasyl: ";
for (int x : vas) cout << x << " "; // 输出Vasyl的货物编号
cout << endl;
cout << "Petro: ";
for (int x : pet) cout << x << " "; // 输出Petro的货物编号
cout << endl;
}
return 0;
}