问题 E: 【宽搜入门】巧妙取量
时间限制: 2 Sec 内存限制: 128 MB
提交: 64 解决: 22
[提交][状态][讨论版][命题人:外部导入]
题目描述
【题目描述】
有三个容器,容量分别为 a,b,c(a> b > c ),一开始a装满油,现在问是否只靠abc三个容器量出k升油。如果能就输出“yes”,并且说明最少倒几次,否则输出“no”。例如:10升油在10升的容器中,另有两个7升和3升的空容器,要求用这三个容器倒油,使得最后在abc三个容器中有一个刚好存有5升油,问最少的倒油次数是多少?(每次倒油,A容器倒到B容器,或者A内的油倒完,或者B容器倒满。
10 7 3
(10 0 0)
(3 7 0):第一次
(3 4 3):第二次
(6 4 0):第三次
(6 1 3):第四次
(9 1 0):第五次
(9 0 1):第六次
(2 7 1):第七次
(2 5 3):第八次,出现5了。
Input
【输入格式】
有多组测试数据。
输入a,b,c, k四个正整数( 100 ≥ a > b > c≥1 , 1≤k< 100 )
Output
【输出格式】
如果能得到k就输出两行。
第一行“yes”,第二行为最少的次数
否则输出“no”
Sample Input
10 7 3 5
Sample Output
yes
8
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int v[3], k;
bool f[101][101][101];//判定是否已出现过
struct node {
int w[3], step;
}s, t;//从s(倒水前状态)到t(倒水后状态)
void BFS() {
queue<node> q;
if (v[0] == k) {
cout << "yes" << endl << 0 << endl;
return;
}
s.w[0] = v[0]; s.w[1] = s.w[2] = s.step = 0;
q.push(s);
while (!q.empty()) {
s = q.front();
q.pop();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i != j&&s.w[j] < v[j] && s.w[i]>0) {//可以从i向j倒水
t = s;
t.step++;
if (s.w[i] >= v[j] - s.w[j]) {//若i有剩余
t.w[i] -= v[j] - s.w[j];
t.w[j] = v[j];
}
else {//否则i全倒入j
t.w[i] = 0;
t.w[j] += s.w[i];
}
if (t.w[i] == k || t.w[j] == k) {
cout << "yes" << endl << t.step << endl;
return;
}
if (!f[t.w[0]][t.w[1]][t.w[2]]) {
f[t.w[0]][t.w[1]][t.w[2]] = true;
q.push(t);
}
}
}
}
}
cout << "no" << endl;
}
int main() {
while (cin >> v[0] >> v[1] >> v[2] >> k) {
memset(f, 0, sizeof(f));
BFS();
}
return 0;
}