UVa 10603 Fill( BFS + 判重)

本文深入探讨隐式图搜索的概念及其关键要素,着重解析如何通过记录状态和状态转移来解决这类问题。以具体例子为例,阐述了状态转移的两种方式,并通过BFS函数实现状态遍历的过程。文章最后提供了详细的代码实现,帮助读者理解隐式图搜索的实践应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

隐式图搜索是最难受的题目之一,但是一般情况下,如果是隐式图搜索的话,都要记录状态,都会有一个状态的转移。

比如这道题,其实状态是只有第三个杯子里面有装满水,第一和第二个杯子里面都是空,那么这个状态可以转移的话,只能有两个方向的转移。第一是想第一杯子倒水,第二是向第二个杯子倒水,那无论是那种转移,只要这个状态曾经存在过,那么这个状态能转移到的状态就已经遍历过,并且每个状态都要有一个唯一的标识,可以通过这个标识来确认这个状态是否已经存在过!如果存在过,就不要再对这个状态进行转移了。所以对于隐式图的搜索,最重要的是怎么记录状态,以及分析状态可以转移的方向。

那么这道题,对于一个状态,一共最多有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);
    }
}




### C++ 中使用 BFS 和 For 循环替代 DFS 的实现 在解决网格类问题时,广度优先搜索 (BFS) 可作为深度优先搜索 (DFS) 的有效替代方案。对于岛屿等问题而言,可以利用队列来管理待访问的位置,并通过 `for` 循环迭代处理这些位置。 #### 岛屿数量问题的 BFS 解决方案 下面是一个基于 BFS 来计算岛屿数量的例子: ```cpp #include <vector> #include <queue> using namespace std; class Solution { public: int numIslands(vector<vector<char>>& grid) { if (grid.empty() || grid[0].empty()) return 0; int rows = grid.size(); int cols = grid[0].size(); int islands = 0; vector<pair<int, int>> directions{{0,-1},{-1,0},{0,1},{1,0}}; for (int r = 0; r < rows; ++r){ for (int c = 0; c < cols; ++c){ if (grid[r][c] == '1'){ ++islands; queue<pair<int, int>> q; q.push({r,c}); while (!q.empty()){ auto [row, col] = q.front(); q.pop(); // 如果当前位置已经被标记,则跳过 if(grid[row][col]=='0') continue; // 将当前陆地标记为已访问 grid[row][col]='0'; // 对四个方向上的相邻节点进行探索 for(auto& dir : directions){ int newRow = row + dir.first; int newCol = col + dir.second; // 检查边界条件以及是否是未访问过的土地 if(newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && grid[newRow][newCol] == '1') q.push({newRow,newCol}); } } } } } return islands; } }; ``` 此代码片段展示了如何使用 BFS 方法遍历整个地图并统计岛屿的数量。每当遇到一个新的岛屿部分(即值为 `'1'`),就启动一次新的 BFS 查找过程直到该岛完全被淹没为止。在此过程中,所有属于同一座岛屿的部分都会被设置成水 (`'0'`) 以防止复计数[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值