較原文有兩處改動:1)以二維數組代替map,更簡潔有效 2)輸出操作過程,改進後更容易理解(原文好像也是對的,但是說不通)
原文地址POJ3414-Pots
#include<iostream>
#include<string>
#include<memory.h>
using namespace std;
int v1,v2; //兩個瓶子的容量
int c; //目標殘餘水量
bool vist[101][101];
int k1,k2; //在某狀態時兩個瓶子的剩餘水量,temporary
typedef class
{
public:
int x,y; //當前狀態(兩個瓶子中的水量)
int pos; //記錄前一狀態在隊列queue中的下標
int step; //當前步數
}process;
void fill(int i)
{
switch(i)
{
case 1: {k1=v1; return;}
case 2: {k2=v2; return;}
}
}
void drop(int i)
{
switch(i)
{
case 1: {k1=0; return;}
case 2: {k2=0; return;}
}
}
void pour(int i,int j)
{
switch(i)
{
case 1: // v1 to v2
{
if(k1+k2<=v2)
{
k2=k1+k2;
k1=0;
}
else
{
k1=k1+k2-v2;
k2=v2;
}
return;
}
case 2: // v2 to v1
{
if(k1+k2<=v1)
{
k1=k1+k2;
k2=0;
}
else
{
k2=k1+k2-v1;
k1=v1;
}
return;
}
}
}
void BFS(void)
{
int operation[1000]={0}; //當前步的操作: 1z0:清空z瓶子 2z0:裝滿z瓶子 3xy:從x瓶倒向y瓶
process queue[1000]; //狀態隊列
int head,tail;
queue[head=0].x=0;
queue[tail=0].y=0;
queue[tail++].step=0;
while(head<tail)
{
process p=queue[head];
if(p.x==c || p.y==c) //得到要求的剩餘水量c
{
cout<<p.step<<endl;
/*下標回溯,輸出操作過程*/
int ps=p.step;
int* steps=new int[ps+1]; //從1到p.step順序記錄各步操作的下標,不使用steps[0]
steps[ps--]=head;
while(ps)
{
steps[ps]=queue[ steps[ps+1] ].pos;
ps--;
}
for(int i=1;i<=p.step;i++)
{
int temp=operation[ steps[i] ]; //注意各個數組間的下標關係
switch(temp/100)
{
case 1:
{
cout<<"DROP("<<(temp/10)%10<<')'<<endl;
break;
}
case 2:
{
cout<<"FILL("<<(temp/10)%10<<')'<<endl;
break;
}
case 3:
{
cout<<"POUR("<<(temp/10)%10<<','<<temp%10<<')'<<endl;
break;
}
}
}
delete steps;
return;
}
/*裝滿v1*/
k1=p.x;
k2=p.y;
fill(1);
if(!vist[k1][k2])
{
vist[k1][k2]=true;
queue[tail].x=k1;
queue[tail].y=k2;
queue[tail].step=p.step+1; //當前的操作步數
queue[tail].pos=head; //前一步操作在queue[]中的下標
operation[tail++]=210; //當前的操作
}
/*裝滿v2*/
k1=p.x;
k2=p.y;
fill(2);
if(!vist[k1][k2])
{
vist[k1][k2]=true;
queue[tail].x=k1;
queue[tail].y=k2;
queue[tail].step=p.step+1;
queue[tail].pos=head;
operation[tail++]=220;
}
/*清空v1*/
k1=p.x;
k2=p.y;
drop(1);
if(!vist[k1][k2])
{
vist[k1][k2]=true;
queue[tail].x=k1;
queue[tail].y=k2;
queue[tail].step=p.step+1;
queue[tail].pos=head;
operation[tail++]=110;
}
/*清空v2*/
k1=p.x;
k2=p.y;
drop(2);
if(!vist[k1][k2])
{
vist[k1][k2]=true;
queue[tail].x=k1;
queue[tail].y=k2;
queue[tail].step=p.step+1;
queue[tail].pos=head;
operation[tail++]=120;
}
/*v1倒向v2*/
k1=p.x;
k2=p.y;
pour(1,2);
if(!vist[k1][k2])
{
vist[k1][k2]=true;
queue[tail].x=k1;
queue[tail].y=k2;
queue[tail].step=p.step+1;
queue[tail].pos=head;
operation[tail++]=312;
}
/*v2倒向v1*/
k1=p.x;
k2=p.y;
pour(2,1);
if(!vist[k1][k2])
{
vist[k1][k2]=true;
queue[tail].x=k1;
queue[tail].y=k2;
queue[tail].step=p.step+1;
queue[tail].pos=head;
operation[tail++]=321;
}
head++;
}
cout<<"impossible"<<endl;
return;
}
int main(void)
{
while(cin>>v1>>v2>>c){
memset(vist,false,sizeof(vist));
BFS();
}
return 0;
}