问题 E: 【宽搜入门】巧妙取量
时间限制: 2 Sec 内存限制: 128 MB
提交: 229 解决: 73
[提交][状态][讨论版][命题人:外部导入]
题目描述
【题目描述】
有三个容器,容量分别为 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
AC代码:
#include<iostream>
#include<map>
#include<queue>
using namespace std;
int a, b, c, k,s[3]; //s数组对应a,b,c
struct node
{
int v[3];
int step;
};
int change_to(node t)
{
int temp = 0;
temp = t.v[0] * 10000 + t.v[1] * 100 + t.v[2];
return temp;
}
bool ope(node &t,int i,int j) //i倒入j
{
if (t.v[i] > 0 && t.v[j]<s[j])
{
if (t.v[i] + t.v[j] > s[j])
{
t.v[i] -= s[j] - t.v[j];
t.v[j] = s[j];
}
else
{
t.v[j] += t.v[i];
t.v[i] = 0;
}
return true;
}
return false;
}
int main()
{
while (cin >> a >> b >> c >> k)
{
if (a == k)
{
cout << "yes\n0\n";
continue;
}
map <int, bool> M;
s[0] = a, s[1] = b, s[2] = c;
node start, end;
start.v[0] = a, start.v[1] = start.v[2] = start.step = 0;
M[change_to(start)] = 1;
queue <node> Q;
Q.push(start);
int flag = 0;
while (!Q.empty())
{
node vn = Q.front();
Q.pop();
for (int i = 0; i <3; i++)
{
for (int j = 0; j < 3; j++)
{
node temp = vn;
if (i != j&&ope(temp, i, j))
{
if (M[change_to(temp)] == 0)
{
M[change_to(temp)] = 1;
temp.step = vn.step + 1;
if (temp.v[0] == k || temp.v[1] == k || temp.v[2] == k)
{
flag = 1;
end = temp;
break;
}
Q.push(temp);
}
}
}
if (flag)break;
}
if (flag)break;
}
if (flag)
{
cout << "yes\n";
cout << end.step << endl;
}
else cout << "no\n";
}
return 0;
}