算法-3个水桶8升水

问题描述:
有3个水桶的容量为8升,5升和3升。
8升水桶里面装满了水。如果利用另外两个桶,得到4升水?

思路:
水桶里的水量看作是状态。倒水的动作,使得状态变迁。
遍历所有的倒水动作,得到所有的状态。
因此问题就变成,如何从初始状态(8,0,0),经过倒水动作的触发,得到最终状态(4,4,0)?

利用对所有状态的分析,想到所有的状态,可以以树的形式表示。遍历状态树可以用广度,也可以用深度优先搜索。
因为要得到倒水的序列,想到用深度优先搜索的方式来遍历解空间。
深度搜索可能会遇到环,因此利用deque存储以前搜索过的状态,如果搜索过了,则跳过。这是一种剪枝的方法。


#ifndef _BUCKET_H_
#define _BUCKET_H_

#ifdef __cplusplus
extern "C" {
#endif

#define BUCKETS_COUNT   (3)

struct BucketState
{
    int bucket_s[BUCKETS_COUNT];
};

int buckets_dump_water_demo();

#ifdef __cplusplus
}
#endif

#endif

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <deque>
#include "bucket.h"

using namespace std;
int bucket_init_state[BUCKETS_COUNT]  = {8, 0, 0};
int bucket_final_state[BUCKETS_COUNT] = {4, 4, 0};
int bucket_capicity[BUCKETS_COUNT] = {8, 5, 3};

void PrintStates(BucketState& cur_state)
{
    for(int i = 0; i < BUCKETS_COUNT; ++i)
    {
        cout << cur_state.bucket_s[i] << " ";
    }
    cout << endl;
}
void print_result(deque<BucketState>& state)
{
    deque<BucketState>::iterator *pIter = new deque<BucketState>::iterator;
    cout << "Find Result : " << endl;
    for (*pIter = state.begin(); *pIter != state.end(); (*pIter)++)
    {
        PrintStates(**pIter);
    }

    cout << endl << endl;
    return;
}

int is_same_bucket_state(BucketState& state1, BucketState& state2)
{
    int i = 0;
    for (i = 0; i < BUCKETS_COUNT; i++)
    {
        if (state1.bucket_s[i] != state2.bucket_s[i])
        {
            return 0;
        }
    }
    return 1;
}


int is_exist(deque<BucketState>& state, BucketState& cur_state)
{
    deque<BucketState>::iterator *pIter = new deque<BucketState>::iterator;
    for (*pIter = state.begin(); *pIter != state.end(); (*pIter)++)
    {
        if (is_same_bucket_state(**pIter, cur_state))
        {
            return 1;
        }
    }
    return 0;
}


int can_dump_water(BucketState& cur_state, int from, int to, BucketState& next_state)
{
    if ((from != to)&&(cur_state.bucket_s[from] != 0)&&(cur_state.bucket_s[to] != bucket_capicity[to]))
    {
        int i = 0;
        for (i = 0; i < BUCKETS_COUNT; i++)
        {
            next_state.bucket_s[i] = cur_state.bucket_s[i];
        }
        if ((cur_state.bucket_s[from] + cur_state.bucket_s[to]) >= bucket_capicity[to])
        {
            next_state.bucket_s[from] = (cur_state.bucket_s[from] + cur_state.bucket_s[to]) -bucket_capicity[to];
            next_state.bucket_s[to] = bucket_capicity[to];
        }
        else
        {
            next_state.bucket_s[from] = 0;
            next_state.bucket_s[to] = cur_state.bucket_s[from] + cur_state.bucket_s[to];
        }
        return 1;
    }
    return 0;
}

void search_state(deque<BucketState>& state);

void search_action(deque<BucketState>& state, BucketState& cur_state, int from, int to)
{
    BucketState next;
    if (!can_dump_water(cur_state, from, to, next))
    {
        return;
    }
    if (!is_exist(state, next))
    {
        state.push_back(next);
        search_state(state);
        state.pop_back();
    }

    return;
}

int is_final_state(BucketState& cur_state)
{
    int i = 0;
    for (i = 0; i < BUCKETS_COUNT; i++)
    {
        if (cur_state.bucket_s[i] != bucket_final_state[i])
        {
            return 0;
        }
    }
    return 1;
}

void search_state(deque<BucketState>& state)
{
    BucketState current = state.back();
    if (is_final_state(current))
    {
        print_result(state);
    }
    int i = 0;
    int j = 0;
    for (i = 0; i < BUCKETS_COUNT; i++)
    {
        for (j = 0; j < BUCKETS_COUNT; j++)
        {
            search_action(state, current, i, j);
        }
    }
}

int buckets_dump_water_demo()
{
    deque<BucketState> states;
    BucketState init_buckets;
    int i = 0;
    for (i = 0; i < BUCKETS_COUNT; i++)
    {
        init_buckets.bucket_s[i] = bucket_init_state[i];
    }

    states.push_back(init_buckets);
    search_state(states);
    return 0;
}

参考:《算法的乐趣》
代码:https://github.com/hopeworker/work_utility

发布了83 篇原创文章 · 获赞 4 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/hope_worker/article/details/46456787