给定 2
个没有刻度容器,对于任意给定的容积,求出如何只用两个瓶装出
L
升
的水,如果可以,输出步骤,如果不可以,请输出
No Solution
。
两个方法DFS和BFS
DFS(自己瞎写的):
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int target;
int x_m, y_m;
vector<int>v; //记录出现过的状态
string process = "";
bool flag = false;
string result = "no solution";
void fun(int x, int y) {
cout << x << y << endl;
if (x == target || y == target) {
result = "找到了!";
return;
}
if (x > x_m) x = x_m; //以防万一检查一下
if (y > y_m) y = y_m;
for (int i = 0; i < v.size(); i++) {
//如果要进行的操作的结果会出现重复,就不往下递归?
if (x * 10 + y == v[i] && flag == true) {
string x = "n";
return;
}
if (v.size() == (x_m + 1) * (y_m + 1)) {
string x = "no solution because of size";
return;
}
}
if (x * 10 + y != 0) //这个判断句和flag都是为了防止一开始出错,后面就没用了
{
v.push_back(x * 10 + y);
flag = true;
}
//总共6个大的if语句
if (x != 0) {
int f = 0;
for (int i = 0; i < v.size(); i++) {
if (y == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把x容器倒空" << endl;
fun(0, y);
}
}
if (y != 0) {
int f = 0;
for (int i = 0; i < v.size(); i++) {
if (x * 10 == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把y容器倒空" << endl; //这里刚刚有的x=0,y=5在这里又没了
fun(x, 0);
}
}
if (y != y_m) {
int f = 0;
for (int i = 0; i < v.size(); i++) {
if (x * 10 + y_m == v[i] && flag == true) {
f = 1; //1表示不能执行下面的操作
}
}
if (f == 0) {
cout << "把y容器填满" << endl;
fun(x, y_m);
}
}
if (x != x_m) {
int f = 0;
for (int i = 0; i < v.size(); i++) {
if (x_m * 10 + y == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把x容器填满" << endl;
fun(x_m, y);
}
}
//如果一边还没满,另一边还有水。往下再分两种情况
//y导入x
if (x_m != x && y != 0) {
int f = 0;
int kong = x_m - x;
if (y >= kong) {
for (int i = 0; i < v.size(); i++) {
if (x_m * 10 + y - kong == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把y导入x" << endl;
fun(x_m, y - kong);
}
}
if (y < kong) {
for (int i = 0; i < v.size(); i++) {
if ((x + y) * 10 == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把y导入x" << endl;
fun(x + y, 0);
}
}
}
//把x导入y
if (y_m != y && x != 0) {
int f = 0;
int kong = y_m - y;
if (x >= kong) {
for (int i = 0; i < v.size(); i++) {
if ((x - kong) * 10 + y_m == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把x导入y" << endl;
fun(x - kong, y_m);
}
}
if (x < kong) {
for (int i = 0; i < v.size(); i++) {
if (x + y == v[i]) {
f = 1;
}
}
if (f == 0) {
cout << "把x导入y" << endl;
fun(0, x + y);
}
}
}
}
int main() {
//后面改成double类型
cout << "请给出两个瓶子的容量是多少升?" << endl;
cin >> x_m >> y_m;
cout << "想得到是多少升?" << endl;
cin >> target;
v.push_back(0);
fun(0, 0);
cout << result << endl;
return 0;
}
BFS:网上参考
//倒水问题
#include<iostream>
#include<queue>
using namespace std;
struct node//状态节点,储存a、b水量和操作
{
int a;
int b;
int step;
};
int a, b, c;
int vis[200][200]; //visit,保存(a,b)的坐标,比如如果有水量(3,2),那么这个点都被标记为1。
//这种标记方法比用vector遍历好用多了!!!!学习了
node path[200][200];
void judge_step(int a, int b);
int bfs()
{
queue<node>q;//使用队列实现的bfs
node now, next;
now.a = 0;
now.b = 0;
now.step = 0;
q.push(now);//入队
while (q.size())
{
now = q.front();
q.pop();
if (now.a == c || now.b == c)//说明找到了方案
{
cout << now.step << "\n";
judge_step(now.a, now.b);
return 1;
}
node pre; //记录路径
pre.a = now.a, pre.b = now.b;
if (now.a < a && !vis[a][now.b])//if 可以倒满a,并且倒完之后的情况还没有发生过,then。
//每次都这么判断就能把所有情况都遍历一遍。我的深度优先搜索应该也能所有情况都搞一遍
{
next.a = a;
next.b = now.b;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
pre.step = 1;
path[next.a][next.b] = pre;
}
if (now.b < b && !vis[now.a][b])//可以倒满b
{
next.a = now.a;
next.b = b;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
pre.step = 2;
path[next.a][next.b] = pre;
}
if (now.a > 0 && !vis[0][now.b])
{
next.a = 0;
next.b = now.b;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
pre.step = 3;
path[next.a][next.b] = pre;
}
if (now.b > 0 && !vis[now.a][0])
{
next.a = now.a;
next.b = 0;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
pre.step = 4;
path[next.a][next.b] = pre;
}
//a往b倒
if (now.a && now.b < b)
{
pre.step = 5;
if (now.a >= b - now.b && !vis[now.a - (b - now.b)][b])//能倒满
{
next.a = now.a - (b - now.b);
next.b = b;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
path[next.a][next.b] = pre;
}
else if (!vis[0][now.b + now.a])//不能倒满
{
next.a = 0;
next.b = now.b + now.a;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
path[next.a][next.b] = pre;
}
}
//b往a倒
if (now.b && now.a < a)
{
pre.step = 6;
if (now.b >= a - now.a && !vis[a][now.b - (a - now.a)])//能倒满
{
next.a = a;
next.b = now.b - (a - now.a);
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
path[next.a][next.b] = pre;
}
else if (!vis[now.a + now.b][0])//不能倒满
{
next.a = now.a + now.b;
next.b = 0;
next.step = now.step + 1;
q.push(next);
vis[next.a][next.b] = 1;
path[next.a][next.b] = pre;
}
}
}
return 0;
}
void judge_step(int a, int b)
{
if (a == 0 && b == 0)
{
return;
}
judge_step(path[a][b].a, path[a][b].b);
if (path[a][b].step == 1)//这代表了bfs的六个方向
{
cout << "fill(a)" << "\n";
}
if (path[a][b].step == 2)
{
cout << "fill(b)" << "\n";
}
if (path[a][b].step == 3)
{
cout << "empty(a)" << "\n";
}
if (path[a][b].step == 4)
{
cout << "empty(b)" << "\n";
}
if (path[a][b].step == 5)
{
cout << "pour(a, b)" << endl;
}
if (path[a][b].step == 6)
{
cout << "pour(b, a)" << "\n";
}
}
int main()
{
cout << "请输入a、b杯容量和目标水量:";
cin >> a >> b >> c;
cout << "\n";
if (!bfs())
cout << "impossible" << "\n";
return 0;
}
/*
3 5 4
2 8 5
4 9 6
*/
BFS才能找到最短路径,即最少的步骤去完成任务。