Article Directory
Original title description
Title Description
Pour Problems "fill A" represents A filling cups, "empty A" represents A cup emptied, "pour AB" represented by A is poured into water and the cup B B A cup filling or emptying.
INPUT
Comprising a plurality of sets of input data. Each set of data inputs A, B, C data range 0 <A <= B, C <= B <= 1000, A and B are relatively prime.
OUTPUT
Your program's output will be a series of instructions. These output lines can cause a jar just any unit C comprises water. Finally, each data line of output should be "success". Output lines start from the first column should not be any empty lines or trailing spaces.
SAMPLE INPUT
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
Title repeat
The literal meaning of the title is relatively simple capacity is relatively prime to two cups, one is a, one b, using two cups, pour a glass of water c capacity, and has been the problem solvability.
Problem-solving ideas
Overview ideas
The topic that Italy looks very easy to understand, but the first time possible to think of using the BFS but not greedy, but after a try two approaches, BFS's solution is relatively easy to implement, difficult to think smaller boundary conditions, use for problem-solving. So where narrative BFS Solution:
hidden core idea is to view the problem into BFS may be the type of search, find and convert the relationship between the states and boundary conditions.
Meaning of the questions conversion: The state of the process of pouring two cups of as the same struct, you can convert the issue into question more than two cups of state, to solve the subject can be converted to the BFS search from the initial state to get the final state (A or B = c)
Conversion relations between states:
(Here we use a, b, c representative of the capacity of the cup, A, B represent the state of a certain time cup)
status | Take switching behavior |
---|---|
A>0 | A emptying |
B>0 | Emptied B |
A<a | A filling |
B<b | Filling B |
A< a&& B>0 && A+B<a | B backward A, and pour dissatisfied |
A<a && B>0 && A+B>=a | B Backward A, the A filling |
B<b && A>0 && A+B<b | A backward B, and pour dissatisfied |
B<b && A>0 && A+B>=b | A backward B, and B filling |
BFS boundary conditions:
A=c || B=c
data storage
Pour the number of this issue, the most important data than in the pouring process, the transition between the two states, in order to ensure the BFS process, each transition between two states appear only once, thus guaranteed to find a certain at least, we use the map <status, status>, to store switching behavior between the two states, the BFS into a state, we only need to do this operation on the switching behavior:
void refresh(status &s, status &t)
{
if ( from.find(t) == from.end() )
{ // 特判合法,加入队列
from[t] = s;
Q.push(t);
}
}
You can join the queue to ensure that the state is a new state, that this conversion is legal
Because each be converted to a state BFS is a must judge the legitimacy of, I recommend that this code is encapsulated into a function, it will greatly enhance code readability.
map partner with a little unfamiliar venue: c ++ official documents
to sum up
BFS use a very interesting topic, you can easily find a way to play After the code, the code forces do not ask, but you need to have ideas. BFS is to grasp the core of the transfer and boundary conditions of the state, we will be able to convert complex issues simple BFS board.
Improved point
Whether BFS or DFS final analysis is an enumeration, to traverse a variety of situations, but greedy or better algorithm can reduce the number of access points, saving time, so there may be less time-consuming than the algorithm of this algorithm, but from problem-solving competition point of view, easy to realize the degree of BFS is still better in the face of an implementation method requires time-consuming when the subject is low.
Source problem (c ++)
#include<cstring>
#include<cstdio>
#include<iostream>
#include<map>
#include<queue>
using namespace std;
struct status
{
/* data */
int a,b;
bool operator<(const status &s)const{
if(a!=s.a) return a<s.a;
return b<s.b;
}
bool operator==(const status &s)const{
return a==s.a && b==s.b;
}
};
queue<status> Q;
map<status, status> from;
vector<status> ans;
/* 递归输出方案 */
void print(status &p,int A,int B,int C)
{
ans.push_back(p);
while( from.find(p) != from.end() && (p.a!=0 | p.b!=0))
{
p=from[p];
ans.push_back(p);
}
for(int i=ans.size()-1;i>0;i--)
{
status start=ans[i];
status end=ans[i-1];
if(start.b==end.b)
{
if(start.a<A && end.a==A)
{
printf("fill A\n");
}
else if(start.a>0 && end.a==0)
{
printf("empty A\n");
}
}
else if(start.a==end.a)
{
if(start.b<B && end.b==B)
{
printf("fill B\n");
}
else if(start.b>0 && end.b==0)
{
printf("empty B\n");
}
}
else if(start.a<end.a && start.b>end.b)
{
printf("pour B A\n");
}
else if(start.a>end.a && start.b<end.b)
{
printf("pour A B\n");
}
}
printf("success\n");
}
void refresh(status &s, status &t)
{
if ( from.find(t) == from.end() )
{ // 特判合法,加入队列
from[t] = s;
Q.push(t);
}
}
void bfs(int A, int B, int C)
{
// 起点, 两杯水都空
status s,t; s.a=0; s.b=0;
Q.push(s);
while (!Q.empty())
{
// 取队首
s = Q.front(); Q.pop();
// 特判到达终点
if (s.a == C || s.b == C) {
print(s,A,B,C); // 输出方案
while(!Q.empty())
Q.pop();
from.clear();
ans.clear();
return;
}
// 倒空 a 杯的水
if (s.a > 0) {
t.a = 0; // 倒空
t.b = s.b;// b 杯不变
refresh(s, t);
}
// 同理,倒空 b 杯的水
if (s.b > 0) {
t.b = 0; // 倒空
t.a = s.a;// a 杯不变
refresh(s, t);
}
// a 杯未满,续满 a 杯
if (s.a < A)
{
// 续满 a 杯
t.a = A;
t.b = s.b;
refresh(s, t);
}
// 同理,b 杯未满,续满 b 杯
if (s.b < B)
{
//续满 b 杯
t.a = s.a;
t.b = B;
refresh(s, t);
}
if (s.b != 0 && s.a<A)
{
if (s.a + s.b <= A)
{
t.a = s.a + s.b;
t.b = 0;
refresh(s, t);
} else
{
t.a = A;
t.b = s.a + s.b - A;
refresh(s, t);
}
}
if (s.a != 0 && s.b<B)
{
if (s.a + s.b <= B)
{
t.a = 0;
t.b = s.a + s.b;
refresh(s, t);
} else
{
t.a = s.a + s.b - B;
t.b = B;
refresh(s, t);
}
}
}
printf("-1\n");
}
int main()
{
int a, b, c;
while(cin>>a>>b>>c)
{
bfs(a, b, c);
}
return 0;
}/* 26 29 11 */