三个水杯
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数
N(0<N<50)
表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3
(V1>V2>V3V1<100V3>0)
表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1
样例输出
3
-1
来源
经典题目
上传者
hzyqazasdf
从上图中可看出,是一个回溯的思想。
- 思想:回溯算法 ,利用bfs实现 ,同时为了运算简单,要进行剪枝,去掉不可能的情况(就是不让不可能的情况进入队列的堆栈,或者遇到他们直接返回)
- 这个题告诉我们,并不是只有图论才会用到bfs,dfs。但凡有搜索,回溯的情形,都可以用bfs,dfs
- 广度优先搜索bfs的框架
BFS()
{
int ... ...;//定义一些变量
queue<node> q;
q.push(head);
while(!q.empty())
{
node pr=q.front();
q.pop();
//下面就是对出队的pr进行的操作
if(... ...)
{
... ...
q.push(...);
}
if(...)
{ ... ...
q.push(...);
}
}
}
代码:
//算法思想:回溯算法 利用bfs实现
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef struct{
int w[4];
int step;
}node;
int N;
int V[4],E[4];
bool visited[101][101][101];//用于 剪枝,visited[5][3][7]=true用来标记第1个杯子装5单位水,
//第2个杯子装3单位水,第3个杯子装7单位水已经访问过,
//以后遇到这种情况不用压入队列了
void Pour(int i,int k,node* next)//第i个杯子给k倒水,将结果存储在next中
{
if(next->w[i] <= V[k] - next->w[k])
{
next->w[k]=next->w[i]+next->w[k];
next->w[i]=0;
}
else
{
next->w[i]=next->w[i]-(V[k] - next->w[k]);
next->w[k]=V[k];
}
return;
}
void BFS()
{
queue<node> q;
node start,pr;
memset(visited,false,sizeof(visited));
start.step=0;
start.w[1]=V[1];
start.w[2]=0;
start.w[3]=0;
visited[start.w[1]][start.w[2]][start.w[3]]=true;//竟然忘了这一步
q.push(start);
while(!q.empty())
{
pr=q.front();
q.pop();
if(pr.w[1]==E[1] && pr.w[2]==E[2] && pr.w[3]==E[3])
{
printf("%d\n",pr.step);
return;
}
node next;
//pr中的杯子倒水,将结果存储在next中
//共有6种情况,1倒给2,3 ,2倒给1,3,3倒给1,2 ,所以有下面代码
for(int i=0;i<3;i++)
{
for(int j=1;j<3;j++)
{
int k=(i+j)%3;//此式子可以保证当i+1为1时,k+1取2,3
//i+1=2时,k+1=1,3;i+1=3时,k+1=1,2
next=pr;
Pour(i+1,k+1,&next);
next.step=next.step+1;
if(!visited[next.w[1]][next.w[2]][next.w[3]])
{
visited[next.w[1]][next.w[2]][next.w[3]]=true;
q.push(next);
}
}
}
}
printf("%d\n",-1);
return;
}
int main()
{
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d%d%d",&V[1],&V[2],&V[3]);
scanf("%d%d%d",&E[1],&E[2],&E[3]);
BFS();
}
return 0;
}