最近在室友推荐下玩水量调节大师,就是下图这个玩意儿。有些关卡智商不够用。。。就试了试用代码凑凑,没想到还真凑出来了。(⊙o⊙)…
附上游戏的下载链接:http://www.pc6.com/azyx/245880.html
喝了口水,接下来我们说重点。
首先我们看看这个游戏的规则,只有三个瓶子(目前就玩到这儿,有四个咱们再说),每个瓶子只有四种操作
1、倒水给2号瓶。(假设这个瓶子编号为1)
2、倒水给三号瓶。
3、倒空。
4、接满。
并且给的操作步数也很有限。所以他的结构就是一种树形的结构,每一步之后可以再延伸四步,再往下走。(见下图)
所以刚好用BFS来解。
所以我们只要从上往下一层层来搜索即可。
(搜索咋写的早就忘了,幸好我还有个小博客https://blog.csdn.net/qq_36752486/article/details/77160631,
看了看就试了试。。。)
接下来我们来看代码即可。注释还是很多的。这个代码有个很大的问题就是用了string,在拼接的过程中非常耗时,
考虑到不是打比赛,也不是非常要求效率就没改。(其实就是改成char[]跳了一堆bug,懒得去调试了(~ ̄▽ ̄)~ )
再就是没有剪枝耗费了很多时间。当然我还是没改。233333333333
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<sstream>
using namespace std;
struct Node ///瓶子的类,不不不,结构体
{
int Now[3]; ///当前三个瓶子的水量
int step; ///步数
string operate;
};
Node Begin, End;
int All[3]; ///三个瓶子的总水量。
int vis[101][101][101]; ///visit数组,记录是否访问过,1为真,0为假
int full_bottle, water, last_index;
int T, res;
int Sucess(Node a, Node b, int index) ///结束判断数组,判断是否到达终点
{
return (a.Now[index] == b.Now[index]);
}
/*void PR(Node m)
{
printf("三个瓶子分别的总量:%d,%d,%d\n", m.All[1], m.All[2], m.All[3]);
printf("三个瓶子分别的水量:%d,%d,%d\n", m.Now[1], m.Now[2], m.Now[3]);
printf("当前步数:%d\n", m.step);
}*/
void Init()
{
printf("请依次输入三个瓶子的储水量:");
cin >> All[0] >> All[1] >> All[2];
printf("请依次输入三个瓶子当前水量:");
cin >> Begin.Now[0] >> Begin.Now[1] >> Begin.Now[2];
Begin.step = 0;
printf("请依次输入让几升的瓶子装入几升水:");
cin >> full_bottle >> water;
for(int i = 0; i < 3; i++)
{
if(All[i] == full_bottle)
{
End.Now[i] = water;
last_index = i;
}
}
}
void BFS()
{
queue<Node> Q; ///建立队列,这儿建队有个好处,不用每次完了清空
memset(vis, 0, sizeof(vis));
Q.push(Begin);
vis[Begin.Now[0]][Begin.Now[1]][Begin.Now[2]] = 1;
while(!Q.empty())
{
Node u = Q.front();
Q.pop();
if(Sucess(u, End, last_index)) ///出口
{
res = u.step;
printf("\n 一共需要如下%d步 \n",res);
cout << u.operate<<endl;
break;
}
for(int i = 0; i <= 2; i++) ///三个瓶子之间倒水
{
for(int j = 0; j <= 2; j++)
{
if(i != j)
{
Node over = u;
if(over.Now[i] >= All[j] - over.Now[j]) ///1的水比2空的部分多huozhexiangdeng
{
over.Now[i] = over.Now[i] - (All[j] - over.Now[j]);
over.Now[j] = All[j];
}
else
{
over.Now[j] = over.Now[j] + over.Now[i];
over.Now[i] = 0;
}
over.step = over.step + 1;
stringstream ss;
ss << All[i];
string si = ss.str();
stringstream sss;
sss << All[j];
string sj = sss.str();
string cz = " 把" + si + "升瓶子倒到" + sj + "升瓶子 \n";
over.operate.append(cz);
if(!vis[over.Now[0]][over.Now[1]][over.Now[2]])
{
Q.push(over);
vis[over.Now[0]][over.Now[1]][over.Now[2]] = 1;
}
}
}
Node now = u; ///倒空某个瓶子
now.Now[i] = 0;
now.step = now.step + 1;
// PR(now);
stringstream ss;
ss <<All[i];
string si = ss.str();
string cz = " 倒空" + si + "升瓶子 \n";
now.operate.append(cz);
Q.push(now);
vis[now.Now[0]][now.Now[1]][now.Now[2]] = 1;
Node now_2 = u; ///倒满某个瓶子,其实这两段可以合成一段写的,太懒了,懒得整理
now_2.Now[i] = All[i];
now_2.step = now_2.step + 1;
string cz_2 = " 装满" + si + "升瓶子 \n";
now_2.operate.append(cz_2);
// PR(now_2);
Q.push(now_2);
vis[now_2.Now[0]][now_2.Now[1]][now_2.Now[2]] = 1;
}
}
}
int main()
{
// freopen("H:\\out.txt","w",stdout);
printf("请输入要计算的组数:");
cin >> T;
while(T--)
{
Init();
res = -1;
BFS();
}
return 0;
}