三个水杯

时间限制: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
原题出自:http://acm.nyist.net/JudgeOnline/problem.php?pid=21 简单的宽度优先搜索,三个水杯之间的相互倒水如下图6种情况:

对于每一次倒水都会引起三个水杯水量状态的改变,这样就可以得到如下的一个解空间树:

代码一:比较容易想到的

 #include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
using namespace std; int v1, v2, v3;
bool visit[][][]; //状态是否出现 struct state
{
int a, b, c;
int ceng; //最小步数
}b, e; int BFS()
{
queue<state> q;
while(!q.empty())
q.pop();
q.push(b);
while(!q.empty())
{
state cur = q.front();
q.pop();
visit[cur.a][cur.b][cur.c] = true; if(cur.a == e.a && cur.b == e.b && cur.c == e.c) //找到
return cur.ceng; if(cur.a > && cur.b < v2) //v1->v2
{
state temp = cur;
int tt = min(temp.a, v2 - temp.b);
temp.a -= tt;
temp.b += tt;
if(visit[temp.a][temp.b][temp.c] == false)
{
visit[temp.a][temp.b][temp.c] = true;
temp.ceng++;
q.push(temp);
}
} if(cur.a > && cur.c < v3) //v1->v3
{
state temp = cur;
int tt = min(temp.a, v3 - temp.c);
temp.a -= tt;
temp.c += tt;
if(visit[temp.a][temp.b][temp.c] == false)
{
visit[temp.a][temp.b][temp.c] = true;
temp.ceng++;
q.push(temp);
}
} if(cur.b > && cur.a < v1) //v2->v1
{
state temp = cur;
int tt = min(temp.b, v1 - temp.a);
temp.a += tt;
temp.b -= tt;
if(visit[temp.a][temp.b][temp.c] == false)
{
visit[temp.a][temp.b][temp.c] = true;
temp.ceng++;
q.push(temp);
}
} if(cur.b > && cur.c < v3) //v2->v3
{
state temp = cur;
int tt = min(temp.b, v3 - temp.c);
temp.b -= tt;
temp.c += tt;
if(visit[temp.a][temp.b][temp.c] == false)
{
visit[temp.a][temp.b][temp.c] = true;
temp.ceng++;
q.push(temp);
}
} if(cur.c > && cur.a < v1) //v3->v1
{
state temp = cur;
int tt = min(temp.c, v1 - temp.a);
temp.c -= tt;
temp.a += tt;
if(visit[temp.a][temp.b][temp.c] == false)
{
visit[temp.a][temp.b][temp.c] = true;
temp.ceng++;
q.push(temp);
}
} if(cur.c > && cur.b < v2) //v3->v2
{
state temp = cur;
int tt = min(temp.c, v2 - temp.b);
temp.c -= tt;
temp.b += tt;
if(visit[temp.a][temp.b][temp.c] == false)
{
visit[temp.a][temp.b][temp.c] = true;
temp.ceng++;
q.push(temp);
}
}
}
return -; //没有终状态
} int main()
{
int n;
scanf("%d", &n);
while(n--)
{
memset(visit, false, sizeof(visit));
scanf("%d %d %d", &v1, &v2, &v3);
b.a = v1, b.b = , b.c = , b.ceng = ;
scanf("%d %d %d", &e.a, &e.b, &e.c);
if(v1 < e.a + e.b + e.c)
{
printf("-1\n");
continue;
}
else
printf("%d\n", BFS());
}
return ;
}

方法二:Floyd 算法

Floyd 算法介绍:http://www.cnblogs.com/orange1438/p/4054649.html

 #include <cstdio>
#include <memory.h>
#include <queue> using namespace std; #define EMPTY 0 struct data_type
{
int state[];
int step;
}; int cupCapacity[], targetState[]; bool visited[][][]; bool AchieveTargetState(data_type current)
{
for (int i = ; i < ; i++)
{
if (current.state[i] != targetState[i])
{
return false;
}
}
return true;
} void PourWater(int destination, int source, data_type &cup)
{
int waterYield = cupCapacity[destination] - cup.state[destination];
if (cup.state[source] >= waterYield)
{
cup.state[destination] += waterYield;
cup.state[source] -= waterYield;
}
else
{
cup.state[destination] += cup.state[source];
cup.state[source] = ;
}
} int BFS(void)
{
int i, j, k;
data_type initial;
queue<data_type> toExpandState; memset(visited, false, sizeof(visited));
initial.state[] = cupCapacity[];
initial.state[] = initial.state[] = ;
initial.step = ;
toExpandState.push(initial);
visited[initial.state[]][][] = true; while (!toExpandState.empty())
{
data_type node = toExpandState.front();
toExpandState.pop();
if (AchieveTargetState(node))
{
return node.step;
}
for (i = ; i < ; i++)
{
for (j = ; j < ; j++)
{
k = (i+j)%;
if (node.state[i] != EMPTY && node.state[k] < cupCapacity[k])
{
data_type newNode = node;
PourWater(k, i, newNode);
newNode.step = node.step + ;
if (!visited[newNode.state[]][newNode.state[]][newNode.state[]])
{
visited[newNode.state[]][newNode.state[]][newNode.state[]] = true;
toExpandState.push(newNode);
}
}
}
}
}
return -;
} int main(void)
{
int testNum;
scanf("%d", &testNum);
while (testNum -- != )
{
scanf("%d%d%d", &cupCapacity[], &cupCapacity[], &cupCapacity[]);
scanf("%d%d%d", &targetState[], &targetState[], &targetState[]);
printf("%d\n", BFS());
}
return ;
}

部分转自:http://blog.csdn.net/code_pang/article/details/7802944

NYOJ 21 三个水杯的更多相关文章

  1. nyoj 21三个水杯(BFS + 栈)

    题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=21 思想: 看了一下搜索就来写了这题(BFS 找出最短路径 所以用此来进行搜索) 这题在 ...

  2. NYOJ 21.三个水杯-初始态到目标态的最少次数-经典BFS

    题目传送门:biubiubiu~ 三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子. ...

  3. NYOJ #21 三个水杯(bfs)

    描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标 ...

  4. nyoj 题目21 三个水杯

    三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有 ...

  5. nyoj三个水杯(bfs)

    三个水杯 时间限制:1000 ms  |           内存限制:65535 KB 难度:4   描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互 ...

  6. nyoj 三个水杯

    三个水杯 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只 ...

  7. 三个水杯 (bfs)

    给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的 ...

  8. 三个水杯——java,广度优先搜索

    题目如下: 21-三个水杯 内存限制:64MB 时间限制:1000ms 特判: No通过数:51 提交数:137 难度:4 题目描述: 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个 ...

  9. 三个水杯(BFS)

    三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 给出三个水杯.大小不一,而且仅仅有最大的水杯的水是装满的,其余两个为空杯子. 三个水杯之间相互倒水,而且水杯 ...

随机推荐

  1. table变宽格式

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. WordPress博客搬家注意事项

    博客域名还有一段时间就到期了,准备更换域名和空间,会出现一些问题,我这里在网上收集整理了一下,基本上会遇到两个重要的问题. 首先第一个问题就是数据的搬迁中出现的错误. 我这里用的是phpmyadmin ...

  3. NFC 与 Windows Phone 的那点事儿

    说起NFC这个词儿应该已经不陌生了,在我们的生活中有很多使用场景都是使用的这项技术,例如公交卡,门禁,还有银联的闪付卡等等.并且近些年在移动设备上使用的场景也越来越多,例如 对 NFC TAG 的读写 ...

  4. ubuntu下解决wireshark权限问题

    wireshark要监控eth0,但是必须要root权限才行.但是,直接用root运行程序是相当危险,也是非常不方便的. 解决方法如下: 1.添加wireshark用户组 sudo groupadd ...

  5. VC6.0 error LNK2001: unresolved external symbol _main解决办法

    学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时,编译都已通过.产生连接错误的原因非常多,尤其LNK2001错误 ...

  6. Java 停止一个 Thread

    boolean   flag=true;         public   void   run(){             while(flag){                     ... ...

  7. 推荐一款炫酷的提示框插件SweetAlert

    官方网址 http://t4t5.github.io/sweetalert/ 项目地址 https://github.com/t4t5/sweetalert

  8. oracle 空间数据库说明

    转:http://blog.csdn.net/jing_xin/article/details/4355642 由于最近弄一些空间数据,所以找了些oracle空间数据库的一些知识.下面是汇总: Ora ...

  9. WP8 SqlCE和SqlLite数据存储性能比较

    在平时的开发中一定会用到本地数据存储,除了独立存储外我们还可以选择SqlCE和SqlLite:于是在选择上我们就必须权衡他们两者的性能择优选择. 测试代码:(这个例子是在msdn sqllite例子上 ...

  10. 【网站开发】在新浪SAE上搭建一个博客

    概述 在新浪SAE上搭建一个博客 1.访问新浪SAE站点 http://sae.sina.com.cn/ 2.注册新浪SAE 3.选择应用仓库 4.选择WordPress 5.安装WordPress ...