三个水杯
时间限制:
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
来源
- 经典题目 上传者
-
hzyqazasdf
写这道题的时候我就觉得是一道数学题
于是我试着用数学思想解决他
于是 我有了点发现
三个水杯中,如果三个水杯最终状态都是不满的 无解
............其他的毫无规律
还是老老实实用广搜吧!
为什么不用深搜那?
应为我们不知道应该搜到什么时候可以停止了
一直向下搜,死循环 ,一直互相倒水,银河二号也要超时
如果定一个边界,如搜到第几次还不行就换一条路的话 你也不知道这个边界定在哪里合适,短了容易吧正确答案省掉 长了 容易超时
还不如广搜,没这么多顾虑
直接出错!!!#include<stdio.h> #include<string.h> int e1,e2,e3; int i,j,k=0,l=1,need; bool vis[100][100][100]; struct node { int v[3]; int step; } sb[200]; void ds(int a,int b) { if(sb[k].v[a]!=0&&vis[sb[k].v[0]][sb[k].v[1]][sb[k].v[2]]==false) //判断能否倒水和是否出现过此状态 { int sum=sb[k].v[a]+sb[k].v[b]; //下面开始倒水 if(sum>=sb[k].v[b]) { sb[l].v[b]=sb[0].v[b]; sb[l].v[a]=sum-sb[l].v[b]; } else { sb[l].v[b]=sum; sb[l].v[a]=0; } sb[l].step=sb[k].step+1; l++; } } int bfs(int v1,int v2,int v3) { for(k=0;; k++) //将队列从头遍历到尾 { //printf("%d %d %d\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]); for(i=0; i<3; i++) //遍历6种倒水情况 { for(j=0; j<3; i++) { if(i!=j) { ds(i,j); //倒水函数 将i中的水往 j中倒 } } } if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2]) //如果过程达到了目标状态 那就return 步数 { return sb[k].step; } } return -1; //如果队列都遍历完了 那么就 没有结果 返回-1 } int main() { int n; scanf("%d",&n); while(n--) { int v1,v2,v3,e1,e2,e3; scanf("%d%d%d%d%d%d",&sb[0].v[0],&sb[0].v[1],&sb[0].v[2],&e1,&e2,&e3); k=0,sb[0].step=0; //初始化 memset(vis,false,sizeof(vis)); printf("%d\n",bfs(sb[0].v[0],sb[0].v[1],sb[0].v[2])); } }
-
多明显的错误~for(j=0; j<3; i++)
-
明显的,这排重就没起作用!!!!#include<stdio.h> #include<string.h> int v0[3],e1,e2,e3; int i,j,k=0,l=1,need; bool vis[100][100][100]; struct node { int v[3]; int step; } sb[200]; void ds(int a,int b) { if(sb[k].v[a]!=0) //判断能否倒水和是否出现过此状态 { sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2]; int sum=sb[k].v[a]+sb[k].v[b]; //下面开始倒水 if(sum>=v0[b]) { sb[l].v[b]=v0[b]; sb[l].v[a]=sum-v0[b]; } else { sb[l].v[b]=sum; sb[l].v[a]=0; } if(vis[sb[k].v[0]][sb[k].v[1]][sb[k].v[2]]==false) { //printf(" %d\n",l); sb[l].step=sb[k].step+1; l++; vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=true; //rintf("%d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2]); } } } int bfs(int v1,int v2,int v3) { for(k=0;; k++) //将队列从头遍历到尾 { //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]); for(i=0; i<3; i++) //遍历6种倒水情况 { for(j=0; j<3; j++) { //printf("%d %d***\n",i,j); if(i!=j) { ds(i,j); //倒水函数 将i中的水往 j中倒 } } } if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2]) //如果过程达到了目标状态 那就return 步数 { return sb[k].step; } } return -1; //如果队列都遍历完了 那么就 没有结果 返回-1 } int main() { int n; scanf("%d",&n); while(n--) { scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3); k=0,sb[0].step=0; sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0; //初始化 memset(vis,false,sizeof(vis)); printf("%d\n",bfs(sb[0].v[0],0,0)); } }
-
好吧,把排重步骤的顺序改一下
-
哎#include<stdio.h> #include<string.h> int v0[3],e1,e2,e3; int i,j,k=0,l=1,need; int vis[105][105][105]; struct node { int v[3]; int step; } sb[50000]; void ds(int a,int b) { if(sb[k].v[a]!=0) //判断能否倒水 { sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2]; int sum=sb[k].v[a]+sb[k].v[b]; //下面开始倒水 if(sum>=v0[b]) { sb[l].v[b]=v0[b]; sb[l].v[a]=sum-v0[b]; } else { sb[l].v[b]=sum; sb[l].v[a]=0; } //printf("%d 0.0\n",vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]); if(vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]==0) //判断是否出现过此状态 { //printf(" %d\n",l); sb[l].step=sb[k].step+1; vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=1; l++; //printf("%d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2]); } } } int bfs(int v1,int v2,int v3) { for(k=0;; k++) //将队列从头遍历到尾 { //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]); for(i=0; i<3; i++) //遍历6种倒水情况 { for(j=0; j<3; j++) { //printf("%d %d***\n",i,j); if(i!=j) { ds(i,j); //倒水函数 将i中的水往 j中倒 } } } if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2]) //如果过程达到了目标状态 那就return 步数 { return sb[k].step; } if(k>l) { return -1; //如果队列都遍历完了 那么就 没有结果 返回-1 } } } int main() { int n; scanf("%d",&n); while(n--) { scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3); if(e1+e2+e3!=v0[0]) { printf("-1\n"); } else if(v0[0]==e1&&v0[1]==e2&&v0[2]==e3) { printf("0\n"); } else { k=0,sb[0].step=0; sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0; //初始化 memset(vis,0,sizeof(vis)); printf("%d\n",bfs(sb[0].v[0],0,0)); } } }
-
这个错误又找了很久if(sb[k].v[0]==e1&&sb[k].v[1]==e2&&sb[k].v[2]) //如果过程达到了目标状态 那就return 步数
-
....还有一个问题#include<stdio.h> #include<string.h> int v0[3],e1,e2,e3; int i,j,k=0,l=1,need; int vis[105][105][105]; struct node { int v[3]; int step; } sb[100000] void ds(int a,int b) { if(sb[k].v[a]!=0) //判断能否倒水 { sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2]; int sum=sb[k].v[a]+sb[k].v[b]; //下面开始倒水 if(sum>=v0[b]) { sb[l].v[b]=v0[b]; sb[l].v[a]=sum-v0[b]; } else { sb[l].v[b]=sum; sb[l].v[a]=0; } //printf("%d 0.0\n",vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]); if(vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]==0) //判断是否出现过此状态 { //printf(" %d\n",l); sb[l].step=sb[k].step+1; vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=1; l++; //printf("%d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2]); } } } int bfs(int v1,int v2,int v3) { for(k=0;; k++) //将队列从头遍历到尾 { //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]); for(i=0; i<3; i++) //遍历6种倒水情况 { for(j=0; j<3; j++) { //printf("%d %d***\n",i,j); if(i!=j) { ds(i,j); //倒水函数 将i中的水往 j中倒 if(sb[l-1].v[0]==e1&&sb[l-1].v[1]==e2&&sb[l-1].v[2]==e3) //如果过程达到了目标状态 那就return 步数 { return sb[l-1].step; } } } } if(k>l) { return -1; //如果队列都遍历完了 那么就 没有结果 返回-1 } } } int main() { int n; scanf("%d",&n); while(n--) { scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3); if(e1+e2+e3!=v0[0]) { printf("-1\n"); } else if(v0[0]==e1&&v0[1]==e2&&v0[2]==e3) { printf("0\n"); } else { k=0,sb[0].step=0; sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0; //初始化 memset(vis,0,sizeof(vis)); printf("%d\n",bfs(sb[0].v[0],0,0)); } } }
-
样例
-
6 4 3
-
3 3 0
-
输出应该是2
-
但是是3
-
不是最小情况
-
要是再加入一个min找最下 那么很可能就会超时!!
-
-
哇喀喀喀!终于AC了
-
这题我dbug 了好几天 可能是我太水了!!!#include<stdio.h> #include<string.h> int v0[3],e1,e2,e3; int i,j,k=0,l=1,need; int vis[105][105][105]; struct node { int v[3]; int step; } sb[100000]; void ds(int a,int b) { if(sb[k].v[a]!=0) //判断能否倒水 { sb[l].v[0]=sb[k].v[0],sb[l].v[1]=sb[k].v[1],sb[l].v[2]=sb[k].v[2]; int sum=sb[k].v[a]+sb[k].v[b]; //下面开始倒水 if(sum>=v0[b]) { sb[l].v[b]=v0[b]; sb[l].v[a]=sum-v0[b]; } else { sb[l].v[b]=sum; sb[l].v[a]=0; } //printf("%d 0.0\n",vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]); if(vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]==0) //判断是否出现过此状态 { //printf(" %d\n",l); sb[l].step=sb[k].step+1; vis[sb[l].v[0]][sb[l].v[1]][sb[l].v[2]]=1; l++; //printf("%d %d %d %d^-^\n",sb[l-1].v[0],sb[l-1].v[1],sb[l-1].v[2],sb[l-1].step); } } } int bfs(int v1,int v2,int v3) { for(k=0;; k++) //将队列从头遍历到尾 { //printf("%d %d %d$\n",sb[k].v[0],sb[k].v[1],sb[k].v[2]); for(i=0; i<3; i++) //遍历6种倒水情况 { for(j=0; j<3; j++) { //printf("%d %d***\n",i,j); if(i!=j) { ds(i,j); //倒水函数 将i中的水往 j中倒 if(sb[l-1].v[0]==e1&&sb[l-1].v[1]==e2&&sb[l-1].v[2]==e3) //如果过程达到了目标状态 那就return 步数 { return sb[l-1].step; } } } } if(k>l) { return -1; //如果队列都遍历完了 那么就 没有结果 返回-1 } } } int main() { int n; scanf("%d",&n); while(n--) { scanf("%d%d%d%d%d%d",&v0[0],&v0[1],&v0[2],&e1,&e2,&e3); if(e1+e2+e3!=v0[0]) { printf("-1\n"); } else if(v0[0]==e1) { printf("0\n"); } else { k=0,sb[0].step=0,l=1; sb[0].v[0]=v0[0],sb[0].v[1]=0,sb[0].v[2]=0; //初始化 memset(vis,0,sizeof(vis)); printf("%d\n",bfs(sb[0].v[0],0,0)); } } }
-
可我一直坚持自己dbug!!!
-
不看网上代码!
-
激动坏了!!!1
-
-
-
第一行一个整数N(0<N<50)表示N组测试数据