广搜最短路径变形,(POJ3414)

题目链接:http://poj.org/problem?id=3414

 

解题报告:

1、每个节点都是一个独立的状态

2、这里的状态转移就是有几种出路,4种:1、倒掉a中的水,2、把a中的水倒到b中去,3、倒掉b 中的水,4、把b中的水倒到a中去

3、每次的步骤记录到str[][]中去

4、搜索最短路径

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

struct Node
{
    int a;        ///a杯子里面的水
    int b;        ///b杯子里面的水
    int step;    ///到a,b的情况下所用的步数
    char str[105][105];    ///str[i]存有解时,step=i时的操作
};

int A,B,C;        ///A,B表示两个杯子的容量,C目标容量
bool mark[105][105];    ///mark[i][j]表示在两个杯子在i,j的情况是否标记

bool bfs()
{
    memset(mark,false,sizeof(mark));

    queue<Node>que;
    Node p,tmp;

    p.a=0,p.b=0,p.step=0;
    que.push(p);
    mark[0][0]=true;

    while(!que.empty())
    {
        p=que.front();
        que.pop();

        ///搜索到解
        if(p.a==C||p.b==C)
        {
            printf("%d\n",p.step);
            for(int i=1; i<=p.step; i++)
                printf("%s\n",p.str[i]);
            return true;
        }

        if(p.a==0)
        {
            tmp=p;
            tmp.a=A;///倒满
            tmp.step++;
            strcpy(tmp.str[tmp.step],"FILL(1)");
            if(!mark[tmp.a][tmp.b])
            {
                mark[tmp.a][tmp.b]=true;
                que.push(tmp);
            }
        }
        else if(p.a<=A)    ///可以选择倒掉,也可以选择倒到2杯子中去
        {
            tmp=p;
            tmp.a=0;///倒掉
            tmp.step++;
            strcpy(tmp.str[tmp.step],"DROP(1)");
            if(!mark[tmp.a][tmp.b])
            {
                mark[tmp.a][tmp.b]=true;
                que.push(tmp);
            }
            if(p.b<B)
            {
                tmp=p;
                if(tmp.a+tmp.b<=B)
                {
                    tmp.b+=tmp.a;
                    tmp.a=0;
                }
                else
                {
                    tmp.a=(tmp.b+tmp.a)-B;
                    tmp.b=B;
                }
                tmp.step++;
                strcpy(tmp.str[tmp.step],"POUR(1,2)");
                if(!mark[tmp.a][tmp.b])
                {
                    mark[tmp.a][tmp.b]=true;
                    que.push(tmp);
                }
            }
        }

        if(p.b==0)
        {
            tmp=p;
            tmp.b=B;///倒满
            tmp.step++;
            strcpy(tmp.str[tmp.step],"FILL(2)");
            if(!mark[tmp.a][tmp.b])
            {
                mark[tmp.a][tmp.b]=true;
                que.push(tmp);
            }
        }
        else if(p.b<=B)    ///可以选择倒掉,也可以选择倒到1中
        {
            tmp=p;
            tmp.b=0;    ///倒掉
            tmp.step++;
            strcpy(tmp.str[tmp.step],"DROP(2)");
            if(!mark[tmp.a][tmp.b])
            {
                mark[tmp.a][tmp.b]=true;
                que.push(tmp);
            }
            if(p.a<A)    ///倒到1中
            {
                tmp=p;
                if(tmp.b+tmp.a<=A)
                {
                    tmp.a+=tmp.b;
                    tmp.b=0;
                }
                else
                {
                    tmp.b=(tmp.b+tmp.a)-A;
                    tmp.a=A;
                }
                tmp.step++;
                strcpy(tmp.str[tmp.step],"POUR(2,1)");
                if(!mark[tmp.a][tmp.b])
                {
                    mark[tmp.a][tmp.b]=true;
                    que.push(tmp);
                }
            }
        }
    }

    return false;
}

int main()
{
    while(scanf("%d%d%d",&A,&B,&C)!=EOF)
    {
        if(!bfs()) puts("impossible");
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/TreeDream/p/5373949.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值