poj3414:http://poj.org/problem?id=3414
题意:给你两个罐子的体积,然后让你只用这两个罐子量出给定k体积的水。
题解:这里可以把两个罐子看成是一个二维的图,然后体积的水就是图中其中一个坐标是k的点。可以直接BFS,每次操作就相当于从当前的点向外扩展,并且记录当前的路径,即可。
其中可以用1,2,3,4,5,6六个数字来分别对应六种操作,然后用一个int类型的数组记录路径就可以。
#include<cstring> #include<cstdio> #include<algorithm> #include<cstdio> #include<queue> using namespace std; struct Node{ int counts1;//第一个pot中当前的水 int counts2;//第二个pot中当前的水 int step;//当前的步数 int path[102];//记录到达这一步之前的以及这一步的路径 }; int counts[102][102];//counts【i】【j】表示到达第一个pot中是i, int a,b,k; //第二个pot中是j这种状态所需要的最小的步数 void print(int x){//打印出对印标记的输出路径上每一个数字代表一种操作,六个数字对印六种操作 if(x==1)printf("FILL(1)\n"); if(x==2)printf("FILL(2)\n"); if(x==3)printf("DROP(1)\n"); if(x==4)printf("DROP(2)\n"); if(x==5)printf("POUR(2,1)\n"); if(x==6)printf("POUR(1,2)\n"); } void BFS(){ bool flag=false;//标记是否有解 for(int i=0;i<=100;i++) for(int j=0;j<=100;j++)//初始化 counts[i][j]=10000000; queue<Node>Q; Node tt;//队首元素 tt.counts1=0;//初始时候都是0,0 tt.counts2=0; tt.step=0; counts[0][0]=0;//别忘了注意这里的初始化0 Q.push(tt); while(!Q.empty()){ Node temp=Q.front();//取出队首元素 Q.pop(); int step=temp.step; int sum1=temp.counts1; int sum2=temp.counts2; if(sum1==k){//只要其中一个罐子出现k,则直接输出 printf("%d\n",step); for(int i=1;i<=step;i++)//输出路径 print(temp.path[i]); flag=true; break; } if(sum2==k){ printf("%d\n",step); for(int i=1;i<=step;i++) print(temp.path[i]); flag=true; break; } if(sum1<a&&counts[a][sum2]>step+1){//当第一个罐子没满,这是可以把第一个罐子灌满 Node ttt; ttt.counts1=a; ttt.counts2=sum2; ttt.step=step+1; for(int i=1;i<=step;i++)//复制之前的路径 ttt.path[i]=temp.path[i]; ttt.path[step+1]=1; Q.push(ttt); counts[a][sum2]=step+1; } if(sum2<b&&counts[sum1][b]>step+1){//灌满第二个罐子 Node ttt; ttt.counts1=sum1; ttt.counts2=b; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=2; Q.push(ttt); counts[sum1][b]=step+1; } if(sum1>0&&counts[0][sum2]>step+1){//清空第一个罐子 Node ttt; ttt.counts1=0; ttt.counts2=sum2; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=3; Q.push(ttt); counts[0][sum2]=step+1; } if(sum2>0&&counts[sum1][0]>step+1){//清空第二个罐子 Node ttt; ttt.counts1=sum1; ttt.counts2=0; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=4; Q.push(ttt); counts[sum1][0]=step+1; } if(sum2+sum1>=a&&counts[a][sum2+sum1-a]>step+1){//把第二个导入第一个并且第一个装满之后,第二个还有剩余 Node ttt; ttt.counts1=a; ttt.counts2=sum2+sum1-a; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=5; Q.push(ttt); counts[a][sum2+sum1-a]=step+1; } if(sum2+sum1<a&&counts[sum1+sum2][0]>step+1){////把第二个导入第一个并且第一个装满之后,第二个没有剩余 Node ttt; ttt.counts1=sum1+sum2; ttt.counts2=0; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=5; Q.push(ttt); counts[sum1+sum2][0]=step+1; } if(sum2+sum1>=b&&counts[sum1+sum2-b][b]>step+1){//与上面正好相反 Node ttt; ttt.counts1=sum1+sum2-b; ttt.counts2=b; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=6; Q.push(ttt); counts[sum1+sum2-b][b]=step+1; } if(sum2+sum1<b&&counts[0][sum1+sum2]>step+1){ Node ttt; ttt.counts1=0; ttt.counts2=sum1+sum2; ttt.step=step+1; for(int i=1;i<=step;i++) ttt.path[i]=temp.path[i]; ttt.path[step+1]=6; Q.push(ttt); counts[0][sum1+sum2]=step+1; } } if(!flag)printf("impossible\n"); } int main(){ scanf("%d%d%d",&a,&b,&k); BFS(); }