uva 10603

紫皮书的例题

照着敲了一遍,非原创

大题思路主要是三杯水,而水的总数是知道的,相当于知道第一第二杯水的体积,第三杯水的体积也就确定了。

用第一第二杯水的体积来标记数组是否遍历过

优先队列来找移动体积最少的

主要update_ans()函数进行每次判断

void update_ans(Node & u){
    for(int i = 0;i < 3;i++){
        int d = u.v[i];
        if(ans[d] < 0 || ans[d] > u.dist)
            ans[d] = u.dist;
    }
}

然后就是找第i杯水应该往第j杯水移动水的体积

符合条件进行入队操作

最后在ans数组寻找合适的解……!!!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <stack>
#include <cctype>
#include <string>
#include <malloc.h>
#include <queue>
#include <map>

using namespace std;

const int INF = 0xffffff;
const double esp = 10e-8;
const double Pi = 4 * atan(1.0);
const int Maxn = 200+5;
const int mod = 10000007;
const int dr[] = {1,0,-1,0,-1,1,-1,1};
const int dc[] = {0,1,0,-1,1,-1,-1,1};

struct Node{
    int v[3];
    int dist;
    bool operator < (const Node & rhs)const{
        return dist > rhs.dist;
    }
};

int vis[Maxn][Maxn],cap[3],ans[Maxn];

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;
    }
}

void solve(int a,int b,int c,int d){
    cap[0] = a,cap[1] = b,cap[2] = c;
    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] = c;
    q.push(start);

    vis[0][0] = 1;
    while(!q.empty()){
        Node u = q.top();
        q.pop();
        update_ans(u);
        if(ans[d] >= 0)
            break;
        for(int i = 0;i < 3;i++){
            for(int j = 0;j < 3;j++){
                if(i == j){
                    continue;
                }
                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];///计算将i倒入j的数量
                Node u2;
                memcpy(&u2,&u,sizeof(u));
                u2.dist = u.dist + amount;
                u2.v[i] -= amount;
                u2.v[j] += amount;
                if(!vis[u2.v[0]][u2.v[1]]){
                    vis[ u2.v[0] ][u2.v[1] ] = 1;
                    q.push(u2);
                }
            }
        }
    }
    while(d >= 0){
        if(ans[d] >= 0){
            printf("%d %d\n",ans[d],d);
            return;
        }
        d--;
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("inpt.txt","r",stdin);
#endif
    int T,a,b,c,d;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        solve(a,b,c,d);
    }
    return 0;
}
View Code

 

posted @ 2015-02-14 14:40  寒饼干  阅读(145)  评论(0编辑  收藏  举报