CSP-homework Week2 Problems B implicitly BFS-- pour problem (c ++)

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 */

Published 17 original articles · won praise 2 · Views 1664

Guess you like

Origin blog.csdn.net/qq_43942251/article/details/104679179