紫书uva 10603 优先队列+bfs

https://vjudge.net/problem/UVA-10603

这个题目其实是暴力的一个典范,首先题目说了是最小倒水数,也就是总共次数中转移水的数量,bfs是找最小次数的,因此要用优先队列来改变优先级,将最小倒水数优先,然后是处理如果找不到合适的d,我们要把所有能够找到的值都存放在一个数组里面,然后遍历一次就可以了,我用的vis数组是三维的,用来表示第1,2,3个杯子的水量,和紫书上的略有不同。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
/*
2
96 97 199 62
*/
using namespace std;
int c[4];
int d;
int vis[209][209][209];
int cur[209];
struct node
{
    int a[3];//三个被子的水量
    int m;//倒水最小值
    bool operator< (const node& h) const
    {
        return m>h.m;
    }
} temp,k;
priority_queue <node> q;
void bfs()
{
    int i,j,ans,m,p,x;
    memset(vis,0,sizeof(vis));
    memset(cur,-1,sizeof(cur));
    while(!q.empty()) q.pop();
    temp.a[0]=0;
    temp.a[1]=0;
    temp.a[2]=c[2];//初始值
    temp.m=0;
    vis[temp.a[0]][temp.a[1]][temp.a[2]]=1;
    q.push(temp);
    while(!q.empty())
    {
        temp=q.top();
        q.pop();
        for(i=0; i<=2; i++)
        {
            x=temp.a[i];
            if(cur[x]<0)
            {
                cur[x]=temp.m;
                continue;
            }
            cur[x]=min(cur[x],temp.m);//cur[x]表示第在x的水的时候,最小倒水量
        }
        for(i=0; i<=2; i++) //倒水,当i==j时代表同一杯子
        {
            for(j=0; j<=2; j++) //从第i个杯子倒入第j个杯子
            {
                k=temp;
                if(i==j||k.a[i]==0||c[j]==k.a[j]) continue;
                m=min(k.a[i],c[j]-k.a[j]);//看可以倒多少水
                k.a[i]-=m;
                k.a[j]+=m;
                k.m+=m;
                if(vis[k.a[0]][k.a[1]][k.a[2]]) continue;
                q.push(k);
                vis[k.a[0]][k.a[1]][k.a[2]]=1;

            }
        }
    }
    for(i=d;i>=0;i--)
    {
        if(cur[i]>=0)
        {
            printf("%d %d\n",cur[i],i);
            break;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&c[0],&c[1],&c[2],&d);
        bfs();
    }
}

猜你喜欢

转载自blog.csdn.net/keepcoral/article/details/80115207