隐式图搜索是最难受的题目之一,但是一般情况下,如果是隐式图搜索的话,都要记录状态,都会有一个状态的转移。
比如这道题,其实状态是只有第三个杯子里面有装满水,第一和第二个杯子里面都是空,那么这个状态可以转移的话,只能有两个方向的转移。第一是想第一杯子倒水,第二是向第二个杯子倒水,那无论是那种转移,只要这个状态曾经存在过,那么这个状态能转移到的状态就已经遍历过,并且每个状态都要有一个唯一的标识,可以通过这个标识来确认这个状态是否已经存在过!如果存在过,就不要再对这个状态进行转移了。所以对于隐式图的搜索,最重要的是怎么记录状态,以及分析状态可以转移的方向。
那么这道题,对于一个状态,一共最多有6种转移的方向,最少是没有可以转移的
具体分下,看一下BFS函数
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
using namespace std;
const int N = 2100000;
const int INF = 0x3fffffff;
map <int , int> mp;
int a, b, c, d;
int na, nb, nc, nd;
int T, ans, dx, di;
struct node{
int a, b, c, ans;
}No;
queue<node> q;
void insert( int tmp, node x ) {
if ( !mp.count(tmp) ) {
mp[tmp] = x.ans;
q.push( x );
}
}
int computes( node x ) {
return x.a*1000000+x.b*1000+x.c;
}
void change( int &x, int &y ) {
int tmp = x;
x = y;
y = tmp;
}
bool judge ( node u ) {
if ( dx > abs( u.a - d ) ) {
dx = abs( u.a - d );
ans = u.ans;
di = u.a;
}
if ( dx > abs( u.b - d ) ) {
dx = abs( u.b - d );
ans = u.ans;
di = u.b;
}
if ( dx > abs( u.c - d ) ) {
dx = abs( u.c - d );
ans = u.ans;
di = u.c;
}
if ( dx == 0 ) {
//printf("%d %d %d %d \n", u.a, u.b, u.c, u.ans);
return 1;
}
return 0;
}
void BFS()
{
mp[c] = 0;
No.a = 0, No.b = 0, No.c = c, No.ans = 0;
q.push( No );
while ( !q.empty() ) {
node u = q.front(); q.pop();
int x, tmp;
if ( judge( u ) ) break;
//从a往出到
if ( u.a > 0 ) {
if ( u.b < b ) { //pour into b
tmp = min( u.a, b - u.b );
No.a = u.a - tmp, No.b = u.b + tmp, No.c = u.c, No.ans = u.ans + tmp;
tmp = computes( No );
insert( tmp, No );
}
if ( u.c < c ) { //pour into c
tmp = min( u.a, c - u.c );
No.a = u.a - tmp; No.b = u.b; No.c = u.c + tmp, No.ans = u.ans + tmp;
tmp = computes( No );
insert( tmp, No );
}
}
//从b往出倒
if ( u.b > 0 ) {
if ( u.a < a ) {
tmp = min( u.b, a - u.a );
No.b = u.b - tmp, No.a = u.a + tmp, No.c = u.c, No.ans = u.ans + tmp;
tmp = computes( No );
insert( tmp, No );
}
if ( u.c < c ) {
tmp = min( u.b, c - u.c );
No.b = u.b - tmp, No.c = u.c + tmp, No.a = u.a, No.ans = u.ans + tmp;
tmp = computes( No );
insert( tmp, No );
}
}
//从c往出倒
if ( u.c > 0 ) {
if ( u.a < a ) {
tmp = min( u.c, a - u.a );
No.c = u.c - tmp, No.a = u.a + tmp, No.b = u.b, No.ans = u.ans + tmp;
tmp = computes( No );
insert( tmp, No );
}
if ( u.b < b ) {
tmp = min( u.c, b - u.b );
No.c = u.c - tmp, No.b = u.b + tmp, No.a = u.a, No.ans = u.ans + tmp;
tmp = computes( No );
insert( tmp, No );
}
}
}
}
int main()
{
scanf("%d", &T);
while ( T-- ) {
scanf("%d%d%d%d", &a, &b, &c, &d);
mp.clear();
dx = INF;
while ( !q.empty() ) q.pop();
BFS();
printf("%d %d\n", ans, di);
}
}