[中等] UVa OJ 10603 Fill BFS状态搜索

来源:互联网 发布:pc游戏优化为什么难 编辑:程序博客网 时间:2024/06/05 03:59

题目描述

思路:

其实这道题和我之前写的一篇文章中的题目类似,不过那道题题意比较简单,只需要简单的BFS状态搜索就可以,本题的题意就要复杂一些了,编码也发生了一些变化,因此将其归为中等题目。

要说思路,首先看完题,就知道这是个BFS状态搜索题目,很常规,不过有几个细节要注意:

(1)本题要求的不是最少步数,而是倒水的量,这个很重要。

(2)本题无解时要求出最接近的d',一定要注意这里的d' < d, 不要想当然的认为是绝对值之差最小的。

注意了以上两点,解题基本没有问题了。

对于(1),我们可以采用优先队列,每次从队列中倒水量最少的,对于这个方法,可能不是最好的方法,但是可用的,没问题的,或许你也可以让状态入队时就按照倒水的量入队。

对于(2),比较简单,每次不但和D 比是否相同,如果不相同要记录最靠近的那个状态。

具体代码:

#include <iostream>#include <queue>#include <cstring>using namespace std;struct State{    int vol[3];    long long PourAmt;    State(int a=0,int b=0,int c=0,int d=0)    {        vol[0]=a;        vol[1]=b;        vol[2]=c;        PourAmt=d;    }    bool operator <(const State& rhs) const    {        return PourAmt>rhs.PourAmt;    }};const int maxn=200+2;int MAX[3];int D;bool vis[maxn][maxn][maxn];void pour(int i,int j,State& s){    int& a=s.vol[i];    int& b=s.vol[j];    int bmax=MAX[j];    if(a+b<=bmax)    {        s.PourAmt+=a;        b=a+b;        a=0;    }    else    {        int diff=bmax-b;        b=bmax;        a=a-diff;        s.PourAmt+=diff;    }}int bfs(State& initial,State& ans){    memset(vis,0,sizeof vis);    priority_queue<State> q;    q.push(initial);    int diff=300;    while(!q.empty())    {        State s=q.top();q.pop();        int a=s.vol[0],b=s.vol[1],c=s.vol[2];        if(a==D||b==D||c==D)        {            ans=s;            return -1;        }        else        {            int tdiff=300;            if(D>a)                tdiff=D-a;            if(D>b)                tdiff=min(tdiff,D-b);            if(D>c)                tdiff=min(tdiff,D-c);            if(tdiff<diff)            {                ans=s;                diff=tdiff;            }        }        vis[a][b][c]=true;        for(int i=0;i<3;++i)        {            for(int j=0;j<3;++j)            {                if(i==j)continue;                State sbk=s;                pour(i,j,sbk);                if(!vis[sbk.vol[0]][sbk.vol[1]][sbk.vol[2]])                    q.push(sbk);            }        }    }    return D-diff;}int main(){    //freopen("input.txt","r",stdin);    int kn;    cin>>kn;    for(int kase=0;kase<kn;++kase)    {        for(int i=0;i<3;++i)            cin>>MAX[i];        cin>>D;        State initial(0,0,MAX[2],0);        State ans;        int res=bfs(initial,ans);        cout<<ans.PourAmt<<" ";        if(res==-1)            cout<<D<<endl;        else            cout<<res<<endl;    }    return 0;}