列表

详情


OR95. water

描述

给定四个空杯子,容量分别为S1 S2 S3 S4,允许进行以下操作:

1.  将某个杯子接满水

2.  将某个杯子里的水全部倒掉

3.  将杯子A中的水倒进杯子B,直到A倒空或者B被倒满

问最少要多少步操作才能使得这四个杯子装的水分别为T1 T2 T3 T4


输入描述

第一行四个非负整数S1 S2 S3 S4
第二行四个非负整数T1 T2 T3 T4

输出描述

最少的步数,若无法完成则输出-1

示例1

输入:

0 2 3 4
0 1 2 4

输出:

6

说明:

过程如下:
(0,0,0,0)->(0,2,0,0)->(0,2,3,0)->(0,2,0,3)->(0,0,2,3)->(0,2,2,3)->(0,1,2,4)

原站题解

C++ 解法, 执行用时: 220ms, 内存消耗: 16764KB, 提交时间: 2020-07-29

#include<bits/stdc++.h>
using namespace std;
 
bool mem[64][64][64][64] = {false};
 
bool equal(int s[4], int T[4]){
    return (s[0]==T[0])&&(s[1]==T[1])&&(s[2]==T[2])&&(s[3]==T[3]);
}
 
int bfs(int S[4], int T[4]){
    queue<tuple<int,int,int,int>> q;
    auto x = make_tuple(0,0,0,0);
    q.push(x);
    mem[0][0][0][0] = true;
    int step = 0, cap[4]={0};
    while(!q.empty()){
        int size = q.size();
        while(size--){
            tie(cap[0],cap[1],cap[2],cap[3]) = q.front(); q.pop();
            if(equal(cap, T)){
                return step;
            }
            for(int i=0; i<3; ++i){
                switch(i){
                    case 0: // 将某个杯子倒满
                        for(int j=0, tmp=0; j<4; ++j){
                            tmp = cap[j];
                            cap[j] = S[j];
                            x = make_tuple(cap[0], cap[1], cap[2], cap[3]);
                            if(!mem[cap[0]][cap[1]][cap[2]][cap[3]]){
                                mem[cap[0]][cap[1]][cap[2]][cap[3]]=true;
                                q.push(x);
                            }
                            cap[j] = tmp;
                        }
                        break;
                    case 1: // 将某个杯子倒空
                        for(int j=0, tmp=0; j<4; ++j){
                            tmp = cap[j];
                            cap[j] = 0;
                            x = make_tuple(cap[0], cap[1], cap[2], cap[3]);
                            if(!mem[cap[0]][cap[1]][cap[2]][cap[3]]){
                                mem[cap[0]][cap[1]][cap[2]][cap[3]]=true;
                                q.push(x);
                            }
                            cap[j] = tmp;
                        }
                        break;
                    case 2: // 将杯子j倒向杯子z
                        for(int j=0; j<4; ++j){
                            int tmp1,tmp2,need;
                            for(int z=0; z<4; ++z){
                                if(j==z) continue;
                                tmp1=cap[j], tmp2=cap[z];
                                need = min(cap[j], S[z]-cap[z]);
                                cap[j] -= need;
                                cap[z] += need;
                                x = make_tuple(cap[0], cap[1], cap[2], cap[3]);
                                if(!mem[cap[0]][cap[1]][cap[2]][cap[3]]){
                                    mem[cap[0]][cap[1]][cap[2]][cap[3]]=true;
                                    q.push(x);
                                }
                                cap[j]=tmp1, cap[z]=tmp2;
                            }
                        }
                }//end switch
            }
        }//end inner while
        ++step;
    }//end outer while
    return -1;
}
 
int main(){
    int S[4]={0}, T[4]={0};
    cin>> S[0] >> S[1] >> S[2] >> S[3];
    cin>> T[0] >> T[1] >> T[2] >> T[3];
    if(S[0]==0 && S[1]==0 && S[2]==0 && S[3]==0 && !equal(S,T)){
        cout<< -1 << endl;
    }else{
        int ret = bfs(S, T);
        cout<< ret << endl;
    }
    return 0;
}

C++ 解法, 执行用时: 224ms, 内存消耗: 16760KB, 提交时间: 2020-10-31

#include<bits/stdc++.h>
using namespace std;
 
bool mem[64][64][64][64] = {false};
 
bool equal(int s[4], int T[4]){
    return (s[0]==T[0])&&(s[1]==T[1])&&(s[2]==T[2])&&(s[3]==T[3]);
}
 
int bfs(int S[4], int T[4]){
    queue<tuple<int,int,int,int>> q;
    auto x = make_tuple(0,0,0,0);
    q.push(x);
    mem[0][0][0][0] = true;
    int step = 0, cap[4]={0};
    while(!q.empty()){
        int size = q.size();
        while(size--){
            tie(cap[0],cap[1],cap[2],cap[3]) = q.front(); q.pop();
            if(equal(cap, T)){
                return step;
            }
            for(int i=0; i<3; ++i){
                switch(i){
                    case 0: // 将某个杯子倒满
                        for(int j=0, tmp=0; j<4; ++j){
                            tmp = cap[j];
                            cap[j] = S[j];
                            x = make_tuple(cap[0], cap[1], cap[2], cap[3]);
                            if(!mem[cap[0]][cap[1]][cap[2]][cap[3]]){
                                mem[cap[0]][cap[1]][cap[2]][cap[3]]=true;
                                q.push(x);
                            }
                            cap[j] = tmp;
                        }
                        break;
                    case 1: // 将某个杯子倒空
                        for(int j=0, tmp=0; j<4; ++j){
                            tmp = cap[j];
                            cap[j] = 0;
                            x = make_tuple(cap[0], cap[1], cap[2], cap[3]);
                            if(!mem[cap[0]][cap[1]][cap[2]][cap[3]]){
                                mem[cap[0]][cap[1]][cap[2]][cap[3]]=true;
                                q.push(x);
                            }
                            cap[j] = tmp;
                        }
                        break;
                    case 2: // 将杯子j倒向杯子z
                        for(int j=0; j<4; ++j){
                            int tmp1,tmp2,need;
                            for(int z=0; z<4; ++z){
                                if(j==z) continue;
                                tmp1=cap[j], tmp2=cap[z];
                                need = min(cap[j], S[z]-cap[z]);
                                cap[j] -= need;
                                cap[z] += need;
                                x = make_tuple(cap[0], cap[1], cap[2], cap[3]);
                                if(!mem[cap[0]][cap[1]][cap[2]][cap[3]]){
                                    mem[cap[0]][cap[1]][cap[2]][cap[3]]=true;
                                    q.push(x);
                                }
                                cap[j]=tmp1, cap[z]=tmp2;
                            }
                        }
                }//end switch
            }
        }//end inner while
        ++step;
    }//end outer while
    return -1;
}
 
int main(){
    int S[4]={0}, T[4]={0};
    cin>> S[0] >> S[1] >> S[2] >> S[3];
    cin>> T[0] >> T[1] >> T[2] >> T[3];
    if(S[0]==0 && S[1]==0 && S[2]==0 && S[3]==0 && !equal(S,T)){
        cout<< -1 << endl;
    }else{
        int ret = bfs(S, T);
        cout<< ret << endl;
    }
    return 0;
}

上一题