题目链接:http://poj.org/problem?id=3414
题目描述:
给定三个数A、B、C,表示现有容积为A、B的两个容器,有六种操作,初始状态容器为空,问是否能够经过操作使得中间至少一个容器有C个单位液体。
因为A、B、C的大小均小于100,所以无论能否组成,尝试的最多A、B组合的情况是 100 * 100 , 求最小的步数,直接BFS即可,可以用哈希判重。找到过,往回输出步骤。
<span style="font-size:18px;">#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
using namespace std ;
const int MAXM = 1e5 ;
const int MAXN = 1e4 + 10 ;
int A, B, C ;
bool used[MAXM] ;
int state[MAXN] ; //FILLa, b; DROPa, b; POURa,b, b,a(1 ~ 6)
int res[MAXN] ;
int pos, cur ;
string pri[7] = {"", "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"} ;
//
struct node{
int num, aa, bb, point ;
}rec[MAXN] ;
//
void setValue(int a1, int a2, int a3, int a4){
rec[cur].num = a1 ;
rec[cur].aa = a2 ;
rec[cur].bb = a3 ;
rec[cur].point = a4 ;
}
//
void cal(){
int p ;
pos = -1, cur = 0 ;
memset(used, false, sizeof(used)) ;
setValue(0, 0, 0, 0) ;
used[0] = true ;
pos++ ;
p = -1 ;
while( pos != -1 ){
p++ ;
int vp = p ;
int vv = rec[p].num ;
int va = rec[p].aa ;
int vb = rec[p].bb ;
pos-- ;
//
if( va == C || vb == C ){
cout << vv << endl ;
int tt = 0 ;
res[tt++] = state[p] ;
while( rec[p].point != 0 ){
res[tt++] = state[rec[p].point] ;
p = rec[p].point ;
}
for( int i = tt-1; i >= 0; i-- ){
cout << pri[res[i]] << endl ;
}
return ;
}
//
int tmp1, tmp2 ;
//FILL
tmp1 = 105 * A + vb ;
if( !used[tmp1] ){
used[tmp1] = true ;
cur++, pos++ ;
state[cur] = 1 ;
setValue(vv+1, A, vb, vp) ;
}
tmp2 = 105 * va + B ;
if( !used[tmp2] ){
used[tmp2] = true ;
cur++, pos++ ;
state[cur] = 2 ;
setValue(vv+1, va, B, vp) ;
}
//DROP
tmp1 = vb ;
if( !used[tmp1] ){
used[tmp1] = true ;
cur++, pos++ ;
state[cur] = 3 ;
setValue(vv+1, 0, vb, vp) ;
}
tmp2 = 105 * va ;
if( !used[tmp2] ){
used[tmp2] = true ;
cur++, pos++ ;
state[cur] = 4 ;
setValue(vv+1, va, 0, vp) ;
}
//POUR
if( vb + va < B ){
tmp1 = vb + va ;
if( !used[tmp1] ){
used[tmp1] = true ;
cur++, pos++ ;
state[cur] = 5 ;
setValue(vv+1, 0, va+vb, vp) ;
}
}else{
tmp1 = 105 * (va+vb-B) + B ;
if( !used[tmp1] ){
used[tmp1] = true ;
cur++, pos++ ;
state[cur] = 5 ;
setValue(vv+1, va+vb-B, B, vp) ;
}
}
//
if( vb + va < A ){
tmp2 = 105 * (va+vb) ;
if( !used[tmp2] ){
used[tmp2] = true ;
cur++, pos++ ;
state[cur] = 6 ;
setValue(vv+1, va+vb, 0, vp) ;
}
}else{
tmp2 = 105 * A + (va+vb-A) ;
if( !used[tmp2] ){
used[tmp2] = true ;
cur++, pos++ ;
state[cur] = 6 ;
setValue(vv+1, A, va+vb-A, vp) ;
}
}
}
cout << "impossible" << endl ;
}
//
int main(){
/freopen("1234.txt", "r", stdin) ;
while( cin >> A >> B >> C ){
if( A == C || B == C ){
cout << 1 << endl ;
if( A == C ){
cout << "FILL(1)" << endl ;
}else{
cout << "FILL(2)" << endl ;
}
}else{
cal() ;
}
}
return 0 ;
}</span>