ACM 三水杯


三个水杯

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1
样例输出
3
-1

我还是看了别人写的在自己琢磨了下,这是一个bfs问题 入队所有情况,遍历所有情况。当所有情况都被遍历完了就输出-1。

每次都wa  坑人的memset的头文件是cstring 用的vs2105没有报错 还是自己懂太少了  加油     写的不好见谅

#include<cstdio>

#include<cstdlib>

#include<iostream>

#include<algorithm>

#include<cstring>

#include<math.h>

#include<cmath>

using namespace std;

#define MAX 305

struct water {

int cup[3];

int time;

}Node[MAX];

int V[3], E[3];

int state[105][105][105];

int bfs(){

if (V[0] == E[0] && E[1] == 0 && E[2] == 0)

{ return 0; }

if (V[0] != E[0] + E[1] + E[2])

{ return -1; }

memset(state, 0, sizeof(state));//初始化所有状态为0

memset(Node, 0, sizeof(Node));

int rear = 1, deq = 0;//一个是队的长度另一个是出队的长度

Node[0].cup[0] = V[0];//初始状态放进去

state[Node[0].cup[0]][0][0] = 1;//初始状态标记

while (deq != rear)

{ //每次到法有六种

for (int i = 0;i < 3;i++)

{

for (int j = 0;j < 3;j++)

{

if (i != j&&Node[deq].cup[i]>0&&Node[deq].cup[j]<V[j])

{

int temp = (Node[deq].cup[i]) < (V[j] - Node[deq].cup[j])? (Node[deq].cup[i]):(V[j] - Node[deq].cup[j]);//找到到入得最小值

Node[rear].cup[i] = Node[deq].cup[i] - temp;

Node[rear].cup[j] = Node[deq].cup[j] + temp;

Node[rear].cup[3 - i - j] = Node[deq].cup[3 - i - j];//没有处理的杯子不变

if (state[Node[rear].cup[0]][Node[rear].cup[1]] [Node[rear].cup[2]]==0)

{

state[Node[rear].cup[0]][Node[rear].cup[1]][Node[rear].cup[2]] = 1;//把这个状态赋值为一 Node[rear].time = Node[deq].time + 1;//将上次的次数加一

if (Node[rear].cup[0] == E[0] &&

Node[rear].cup[1] == E[1] &&

Node[rear].cup[2] == E[2])

{return Node[rear].time;}

rear++;

}

}

}

}

deq++;//六种状态都没得出队 }

return -1;}

int main(){

int n;

scanf("%d", &n); while (n--)

{

memset(V, 0, sizeof(V));

memset(E, 0, sizeof(E));

scanf("%d%d%d", &V[0], &V[1], &V[2]);

scanf("%d%d%d", &E[0], &E[1], &E[2]);

printf("%d\n", bfs());

}

return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值