Jugs(罐子)

题目大意:给出两个空杯子,已知这两个空杯子的容量,有无限多的水,再给出要求得到的体积,找出一种方法,得到要求的体积

解决:BFS+路径记录

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
int ca,cb,n,ex,ey;
//有六种选择方案,记录的时候只需要记录下,方案的代号0-6即可
char p[6][20]={"fill A","fill B","pour B A","pour A B","empty A","empty B"};
//bfs离不开判断是否走过,否则会陷入死循环
bool vis[1000][1000];
struct node
{
    int x,y;
    node(){}
    node(int xx,int yy):x(xx),y(yy){}
};
struct pos
{
    int x,y;
    int kind;
    pos(){}
    pos(int xx,int yy,int k):x(xx),y(yy),kind(k){}
};
//存储路径的数组,路径中存放该结点是从哪个结点扩展而来的
pos path[1000][1000];

void bfs()
{
    queue<node> q;
    q.push(node(0,0));
    vis[0][0]=1;
    node now;
    path[0][0]=pos(-1,-1,0);
    while(!q.empty())
    {
        now=q.front();
        if(now.x==n ||now.y==n)return;
       q.pop();
        if(!vis[ca][now.y])
        {//fill A的情况,不一定A为空才能fill A
            vis[ca][now.y]=1;
            q.push(node(ca,now.y));
            path[ca][now.y]=pos(now.x,now.y,0); 
            if(ca==n){ ex=ca; ey=0; return; }
        }
        if(!vis[now.x][cb])
        {
            vis[now.x][cb]=1;
            q.push(node(now.x,cb));
            path[now.x][cb]=pos(now.x,now.y,1); 
            if(cb==n){ ex=0; ey=cb; return; }
        }
        if(now.x!=ca && now.y!=0 )
        {//pour B A的情况,这要分两种状态,一种是将A倒满,一种是将B倒空
            
            if(now.x+now.y >= ca && !vis[ca][now.x+now.y-ca])
            {
                vis[ca][now.x+now.y-ca]=1;
                q.push(node(ca,now.x+now.y-ca));
                path[ca][now.x+now.y-ca]=pos(now.x,now.y,2);
                if(now.x+now.y-ca==n){ ex=ca; ey=now.x+now.y-ca;  return;}
            }
            else if(now.x + now.y < ca && !vis[now.x+now.y][0])
            {
                vis[now.x+now.y][0]=1;
                q.push(node(now.x+now.y,0));
                path[now.x+now.y][0]=pos(now.x,now.y,2);
                if(now.x+now.y==n){ ex=now.x+now.y; ey=0; return;}
            }
        }
        if(now.y!=cb && now.x!=0)
        {//pour A B的情况,一种是将B倒满,一种是将A倒空
            if(now.x+now.y >= cb && !vis[now.x+now.y-cb][cb])
            {
                vis[now.x+now.y-cb][cb]=1;
                q.push(node(now.x+now.y-cb,cb));
                path[now.x+now.y-cb][cb]=pos(now.x,now.y,3);
                if(now.x+now.y-cb==n){ ex=now.x+now.y-cb; ey=cb; return;}
            }
            else if(now.x + now.y < cb && !vis[0][now.x+now.y])
            {
                vis[0][now.x+now.y]=1;
                q.push(node(0,now.x+now.y));
                path[0][now.x+now.y]=pos(now.x,now.y,3);
                if(now.x+now.y==n){ now.x=0; now.y=now.x+now.y; return;}
            }
        }
        if(!vis[0][now.y])
        {//empty A的情况,不一定A满了才能倒空
            vis[0][now.y]=1;
            q.push(node(0,now.y));
            path[0][now.y]=pos(now.x,now.y,4);
        }
        if(!vis[now.x][0])
        {//empty B的情况,不一定B满了才能倒空
            vis[now.x][0]=1;
            q.push(node(now.x,0));
            path[now.x][0]=pos(now.x,now.y,5);
        }
    }
}
void print(int x,int y)
{
    if(path[x][y].x!=-1 && path[x][y].y!=-1)
    {
        print(path[x][y].x,path[x][y].y);
        printf("%s\n",p[path[x][y].kind]);
    }
}
int main()
{
  
    while(cin>>ca>>cb>>n)
    {
        memset(vis,0,sizeof(vis));
        bfs();
        print(ex,ey);    
        cout<<"success"<<endl;    
    }
    system("pause");
    return 0;
}

poj 3414和此题一模一样,但是下边代码,提供一种不同的记录路径的方式,用string来记录,从起始到当前扩展结点的所有路

经,而不是仅仅记录该结点是由哪个结点扩展来的。

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <string>
using namespace std;
int ca,cb,n,ex,ey;
char p[6][20]={"FILL(1)","FILL(2)","POUR(2,1)","POUR(1,2)","DROP(1)","DROP(2)"};
bool vis[105][105];
struct node
{
    int x,y;
    int step;
   //string 方法记录路径
    string way;
    node(){}
    node(int xx,int yy,int s,string w):x(xx),y(yy),step(s),way(w){}
};
string res;
/*
struct pos
{
    int x,y;
    int kind;
    pos(){}
    pos(int xx,int yy,int k):x(xx),y(yy),kind(k){}
};
pos path[105][105];
*/
int bfs()
{
    queue<node> q;
    q.push(node(0,0,0,""));
    vis[0][0]=1;
    node now;
    while(!q.empty())
    {
        now=q.front();
        if(now.x==n ||now.y==n){res=now.way; return now.step;}
        q.pop();
        if(!vis[ca][now.y])
        {
            vis[ca][now.y]=1;
            q.push(node(ca,now.y,now.step+1,now.way+"0"));
            if(ca==n){
            res=q.back().way;
            return now.step+1;
            }
        }
        if(!vis[now.x][cb])
        {
            vis[now.x][cb]=1;
            q.push(node(now.x,cb,now.step+1,now.way+"1"));
            if(cb==n){
            res=q.back().way;
            return now.step+1; 
           }
        }
        if(now.x!=ca && now.y!=0 )
        {
            
            if(now.x+now.y >= ca && !vis[ca][now.x+now.y-ca])
            {
                vis[ca][now.x+now.y-ca]=1;
                q.push(node(ca,now.x+now.y-ca,now.step+1,now.way+"2"));
                if(now.x+now.y-ca==n){ 
                res=q.back().way;
                return now.step+1;
                }
            }
            else if(now.x + now.y < ca && !vis[now.x+now.y][0])
            {
                vis[now.x+now.y][0]=1;
                q.push(node(now.x+now.y,0,now.step+1,now.way+"2"));
                if(now.x+now.y==n){ 
                res=q.back().way;
                return now.step+1;
                }
            }
        }
        if(now.y!=cb && now.x!=0)
        {
            if(now.x+now.y >= cb && !vis[now.x+now.y-cb][cb])
            {
                vis[now.x+now.y-cb][cb]=1;
                q.push(node(now.x+now.y-cb,cb,now.step+1,now.way+"3"));
                if(now.x+now.y-cb==n){
                 res=q.back().way;
                 return now.step+1;
                 }
            }
            else if(now.x + now.y < cb && !vis[0][now.x+now.y])
            {
                vis[0][now.x+now.y]=1;
                q.push(node(0,now.x+now.y,now.step+1,now.way+"3"));
                if(now.x+now.y==n){ 
                 res=q.back().way;
                 return now.step+1;
                 }
            }
        }
        if(!vis[0][now.y])
        {
            vis[0][now.y]=1;
            q.push(node(0,now.y,now.step+1,now.way+"4"));
        }
        if(!vis[now.x][0])
        {
            vis[now.x][0]=1;
            q.push(node(now.x,0,now.step+1,now.way+"5"));
        }
    }
    return -1;
}

int main()
{
  
    cin>>ca>>cb>>n;
    memset(vis,0,sizeof(vis));
    int t=bfs();
    if(t >=0 )
    {
        cout<<t<<endl; 
        int n=res.size();
        for(int i=0;i<n;i++)
            puts(p[res[i]-'0']);
    }
      else cout<<"impossible"<<endl;
    system("pause");
    return 0;
}

 

 

转载于:https://www.cnblogs.com/hpustudent/archive/2011/09/13/2174995.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值