nyoj ACM: 三个水杯(回溯算法 bfs )
2017-04-03 19:45
316 查看
三个水杯
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3V1<100V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
样例输出
来源
经典题目
上传者
hzyqazasdf
从上图中可看出,是一个回溯的思想。
思想:回溯算法 ,利用bfs实现 ,同时为了运算简单,要进行剪枝,去掉不可能的情况(就是不让不可能的情况进入队列的堆栈,或者遇到他们直接返回)
这个题告诉我们,并不是只有图论才会用到bfs,dfs。但凡有搜索,回溯的情形,都可以用bfs,dfs
广度优先搜索bfs的框架
代码:
时间限制: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; }
相关文章推荐
- [ACM_NYOJ_21]三个水杯(BFS广度优先搜索)
- NYOJ 21 三个水杯(bfs,广搜)
- BFS——NYOJ 21 三个水杯
- NYOJ-21-三个水杯【BFS】
- NYOJ 21 三个水杯 (BFS)
- NYOJ 21 三个水杯(BFS)
- nyoj21 三个水杯 (BFS)
- nyoj21 三个水杯(bfs)
- NYOJ三个水杯【BFS】
- BFS——NYOJ 21 三个水杯
- NYOJ 21--三个水杯【BFS】
- NYOJ21 三个水杯 【BFS】
- BFS——NYOJ 21 三个水杯
- nyoj三个水杯(bfs)
- NYOJ - 21 - 三个水杯(隐式图搜索,BFS)
- NYOJ 21 三个水杯(BFS)
- NYOJ-21-三个水杯(BFS 模拟)
- BFS——NYOJ 21 三个水杯
- nyoj 三个水杯 (BFS )
- NYOJ 21-三个水杯(BFS搜索)