[UVa 10603] Fill

Posted corona09

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[UVa 10603] Fill相关的知识,希望对你有一定的参考价值。

Fill

典型的隐式图搜索,将三元组((a,b,c))看作结点,跑最短路算法。
(Dijkstra) 过了,但用 (Bellman-ford) 算法就错了。。。很是无语。。。
借助对拍找到了一组(Dijkstra)对而(Bellman-Ford)错的数据
1 90 149 94

(Bellman-Ford) 算法程序

//Copyright(C)Corona.
//2018-09-28
//Bellman_Ford 
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;
const int MAXN = 200+1;
int dis[MAXN][MAXN],ans[MAXN],cap[3];
int inq[MAXN][MAXN];

struct Node
{
    int v[3],dist;
    Node(int a=0,int b=0,int c=0,int d=0)
    {
        v[0]=a;v[1]=b;v[2]=c;
        dist=d;
    }
}pre[MAXN][MAXN],state[MAXN];

void update_ans(Node u)
{
    for(int i=0;i<3;i++)
    {
        int amount=u.v[i];
        if(ans[amount] < 0 || ans[amount] > u.dist)
        {
            ans[amount] = u.dist;
            state[amount] = u;
        }
    }
    
}
void print_ans(int aim)
{
    int d;
    for(d=aim;d>=0;d--)
        if(ans[d] >=0 )
        {
            cout << ans[d] <<" "<< d <<endl;
            break;
        }
    Node u=state[d];
    printf("(%d,%d,%d)",u.v[0],u.v[1],u.v[2]);
    while(u.v[0] || u.v[1])
    {
        u=pre[u.v[0]][u.v[1]];
        printf("<-(%d,%d,%d)",u.v[0],u.v[1],u.v[2]);
    }
}

queue<Node>Q;

void Bellman_Ford(int a,int b,int c,int d)
{
    cap[0]=a;cap[1]=b;cap[2]=c;
    
    memset(ans,-1,sizeof(ans));
    memset(dis,0x7f,sizeof(dis));   
    memset(inq,0,sizeof(inq));
    
    Q.push(Node(0,0,c,0));
    dis[0][0]=0;
    inq[0][0]=true;
    
    while(!Q.empty())
    {
        Node u=Q.front();Q.pop();
        
        inq[u.v[0]][u.v[1]]=0;
        
        update_ans(u);
        
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                if(i != j)
                {
                    int amount=min(u.v[i],cap[j]-u.v[j]);//将 i 中的水倒入 j 中;
                    
                    Node x=u;
                    
                    x.v[i] -= amount;
                    x.v[j] += amount;
                    x.dist = u.dist + amount;
                    
                    if(dis[x.v[0]][x.v[1]] > x.dist)
                    {
                        dis[x.v[0]][x.v[1]] = x.dist;
                        pre[x.v[0]][x.v[1]] = u;
                        if(!inq[x.v[0]][x.v[1]])
                        {
                            Q.push(x);
                            inq[x.v[0]][x.v[1]]=1;
                        }
                    }
                }
    }
}

int main()
{
    freopen("output.a","w",stdout);
    int T;
    cin >> T;
    while(T--)
    {
        int a,b,c,d;
        cin >>a>>b>>c>>d;
        Bellman_Ford(a,b,c,d);
        print_ans(d);
    }
    return 0;
}

得到的结果与路径.

160 94
(0,55,94)<-(1,55,93)<-(0,56,93)<-(1,56,92)<-(0,57,92)<-(1,57,91)<-(0,58,91)<-(1,58,90)<-(0,59,90)<-(1,59,89)<-(0,60,89)<-(1,60,88)<-(0,61,88)<-(1,61,87)<-(0,62,87)<-(1,62,86)<-(0,63,86)<-(1,63,85)<-(0,64,85)<-(1,64,84)<-(0,65,84)<-(1,65,83)<-(0,66,83)<-(1,66,82)<-(0,67,82)<-(1,67,81)<-(0,68,81)<-(1,68,80)<-(0,69,80)<-(1,69,79)<-(0,70,79)<-(1,70,78)<-(0,71,78)<-(1,71,77)<-(0,72,77)<-(1,72,76)<-(0,73,76)<-(1,73,75)<-(0,74,75)<-(1,74,74)<-(0,75,74)<-(1,75,73)<-(0,76,73)<-(1,76,72)<-(0,77,72)<-(1,77,71)<-(0,78,71)<-(1,78,70)<-(0,79,70)<-(1,79,69)<-(0,80,69)<-(1,80,68)<-(0,81,68)<-(1,81,67)<-(0,82,67)<-(1,82,66)<-(0,83,66)<-(1,83,65)<-(0,84,65)<-(1,84,64)<-(0,85,64)<-(1,85,63)<-(0,86,63)<-(1,86,62)<-(0,87,62)<-(1,87,61)<-(0,88,61)<-(1,88,60)<-(0,89,60)<-(1,89,59)<-(0,90,59)<-(0,0,149)

(Dijkstra) 得到的答案与路径:

109 94
(1,54,94)<-(0,54,95)<-(1,53,95)<-(0,53,96)<-(1,52,96)<-(0,52,97)<-(1,51,97)<-(0,51,98)<-(1,50,98)<-(0,50,99)<-(1,49,99)<-(0,49,100)<-(1,48,100)<-(0,48,101)<-(1,47,101)<-(0,47,102)<-(1,46,102)<-(0,46,103)<-(1,45,103)<-(0,45,104)<-(1,44,104)<-(0,44,105)<-(1,43,105)<-(0,43,106)<-(1,42,106)<-(0,42,107)<-(1,41,107)<-(0,41,108)<-(1,40,108)<-(0,40,109)<-(1,39,109)<-(0,39,110)<-(1,38,110)<-(0,38,111)<-(1,37,111)<-(0,37,112)<-(1,36,112)<-(0,36,113)<-(1,35,113)<-(0,35,114)<-(1,34,114)<-(0,34,115)<-(1,33,115)<-(0,33,116)<-(1,32,116)<-(0,32,117)<-(1,31,117)<-(0,31,118)<-(1,30,118)<-(0,30,119)<-(1,29,119)<-(0,29,120)<-(1,28,120)<-(0,28,121)<-(1,27,121)<-(0,27,122)<-(1,26,122)<-(0,26,123)<-(1,25,123)<-(0,25,124)<-(1,24,124)<-(0,24,125)<-(1,23,125)<-(0,23,126)<-(1,22,126)<-(0,22,127)<-(1,21,127)<-(0,21,128)<-(1,20,128)<-(0,20,129)<-(1,19,129)<-(0,19,130)<-(1,18,130)<-(0,18,131)<-(1,17,131)<-(0,17,132)<-(1,16,132)<-(0,16,133)<-(1,15,133)<-(0,15,134)<-(1,14,134)<-(0,14,135)<-(1,13,135)<-(0,13,136)<-(1,12,136)<-(0,12,137)<-(1,11,137)<-(0,11,138)<-(1,10,138)<-(0,10,139)<-(1,9,139)<-(0,9,140)<-(1,8,140)<-(0,8,141)<-(1,7,141)<-(0,7,142)<-(1,6,142)<-(0,6,143)<-(1,5,143)<-(0,5,144)<-(1,4,144)<-(0,4,145)<-(1,3,145)<-(0,3,146)<-(1,2,146)<-(0,2,147)<-(1,1,147)<-(0,1,148)<-(1,0,148)<-(0,0,149)

(Dijkstra) 算法程序:

//Copyright(C)Corona.
//2018-09-28
//Dijkstra
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN=200+1;
int vis[MAXN][MAXN],dis[MAXN][MAXN];
int cap[3],ans[MAXN];

struct Node
{
    int v[3],dist;
    Node(int a=0,int b=0,int c=0,int d=0)
    {
        v[0]=a;v[1]=b;v[2]=c;
        dist=d;
    }
    
    bool operator < (const Node& rhs)
    const{
        return dist > rhs.dist;
    }
}pre[MAXN][MAXN],state[MAXN];

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

void Dijkstra(int a,int b,int c,int d)
{
    cap[0]=a;cap[1]=b;cap[2]=c;
    
    memset(ans,-1,sizeof(ans));
    memset(vis,0,sizeof(vis));
    memset(dis,0x7f,sizeof(dis));   
    
    priority_queue<Node>Q;
    
    Q.push(Node(0,0,c,0));
    dis[0][0]=0;
    
    while(!Q.empty())
    {
        Node u=Q.top();Q.pop();
        if(vis[u.v[0]][u.v[1]])continue;
        
        vis[u.v[0]][u.v[1]] = 1;
        update_ans(u);
        
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                if(i != j)
                {
                    int amount=min(u.v[i],cap[j]-u.v[j]);//将 i 中的水倒入 j 中;
                    Node x=u;
                    x.v[i] -= amount;x.v[j] += amount;
                    x.dist = u.dist + amount;
                    if(!vis[x.v[0]][x.v[1]] && dis[x.v[0]][x.v[1]] > x.dist)
                    {
                        pre[x.v[0]][x.v[1]] = u;
                        dis[x.v[0]][x.v[1]] = x.dist;
                        Q.push(x);
                    }
                }
    }
}

void print_ans(int aim)
{
    int d;
    for(d=aim;d>=0;d--)
        if(ans[d] >=0 )
        {
            cout << ans[d] <<" "<< d <<endl;
            break;
        }
    Node u=state[d];
    printf("(%d,%d,%d)",u.v[0],u.v[1],u.v[2]);
    while(u.v[0] || u.v[1])
    {
        u=pre[u.v[0]][u.v[1]];
        printf("<-(%d,%d,%d)",u.v[0],u.v[1],u.v[2]);
    }
}
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int a,b,c,d;
        cin >>a>>b>>c>>d;
        Dijkstra(a,b,c,d);
        print_ans(d);
    }
    return 0;
}



以上是关于[UVa 10603] Fill的主要内容,如果未能解决你的问题,请参考以下文章

J - Fill (UVA - 10603)

UVa10603 倒水 Fill-状态空间搜索

UVA-10603-Fill(BFS+优先队列)

[UVa 10603] Fill

UVA - 10603 Fill

Uva-10603 Fill