UVA10603 倒水问题BFS

使用类似dijkstra的方式求解  

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn=200+5;
int vis[maxn][maxn],cap[3],ans[maxn];//ans存储到达当前水量的最短路径
//vis是二维数组,因为知道前2个水杯的水量,第三个水杯即为确定的
struct Node{
    int v[3],dist;
    bool operator < (const Node & rhs) const{
        return dist > rhs.dist;
    } //变量dist表示达到当前状态需要取出的水量
};

void update_ans (const Node & u){
    for(int i=0;i<3;i++){
        int d=u.v[i];
        if(ans[d]<0||u.dist<ans[d]) ans[d]=u.dist; //剪枝
    }//每次更新ans把三个水杯各自水量的最短路径进行更新
}

void bfs (int dest){
    memset(vis,0,sizeof(vis));
    memset(ans,-1,sizeof(ans));
    priority_queue<Node> q;
    Node start;
    start.dist=0;
    start.v[0]=0;start.v[1]=0;start.v[2]=cap[2];
    q.push(start);
    vis[0][0]=1;            //初始第一和第二个水杯都是0
    while(!q.empty()){
        Node u=q.top();
        q.pop();
        update_ans(u);      //对当前已进入队列的结点更新状态
        if(ans[dest]>=0)break;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++) if(i!=j){ //i是出水的水杯编号 j是入水的水杯
                if(u.v[i]==0 || u.v[j] == cap[j]) continue;
                int amount =min(cap[j],u.v[i]+u.v[j])-u.v[j];
                Node u2;
                memcpy(&u2,&u,sizeof(u));   //memcpy可对结构体对象使用
                u2.dist=u.dist+amount;
                u2.v[i] -= amount;
                u2.v[j] += amount;
                if(!vis[u2.v[0]][u2.v[1]]){ // 注意此处v数组的下标是0和1不是i和j
                    vis[u2.v[0]][u2.v[1]] = 1;
                    q.push(u2);
                }
        }
    }
    while(dest >= 0){
        if(ans[dest] >= 0){ //从目标水量d开始,查找距离d最近的d'
            printf("%d %d\n",ans[dest],dest);
            return ;
        }
        dest--;//无法找到当前dest的答案则dest--
    }
}

int main (){
    //freopen("datain.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        int d;
        scanf("%d%d%d%d",&cap[0],&cap[1],&cap[2],&d);
        //输入3个水杯的容量和目标水量,求到达该目标水量的最小倒水量
        bfs(d);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hanker99/article/details/85242911