• 隐式图的遍历


    好久不看都快忘了...

    一些奇怪的问题可以归为隐式图的遍历

    NEUOJ544

    Problem Description
     
    there is an old saying,"You can not do anything without water"or"Water is the source of life". Besides, human beings are made of water. 
    Sister Wang thinks that woman is made of water, so she drinks a lot of water every day. One day, she drinks too much, and can only drink k litre(s) now, but she just has three cups with no scale, which can contain a, b, c litre(s) of water respectively. Each cup can only be filled full with water or be empty. They can be poured from the one to the other one. Since she is too lazy to pour k litre(s). She just want to know how many times at least to pour k litre(s) with these three cups. Yeah, it is just like the problem as you meet when you are in the primary school. Sister Wang want to get the result that there is one cup contains k litre(s).
    At the beginning, each cup can be full or empty. Getting full or pouring empty of each cup does not count the times, only count the times when pouring from each other.
     
    Input
    There are multiple test cases, the number of cases T (1 ≤ T ≤ 20) will be given in the first line of input data. Each test case will include four integer a,b,c and k (1 ≤ k < a,b,c ≤ 100).
     
    Output

    For each test case, output the least times of pouring.

    If you can not get k litre(s),please output -1.

    Sample Input
    1 12 7 3 2
    Sample Output
    2
     
    三个杯子中的水a,b,c可以看成一个状态,用一个queue维护这个状态的转移。
    比较迷惑的地方就是可以不计次数地补满或者倒空杯子
    对于一个从queue中取出的状态a,b,c,我用了个三重循环枚举了所有免费转移到的状态,分别对每个免费转移到的状态尝试插入queue
    由于要多次尝试插入就把尝试插入单独写了个函数
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int maxn = 107, INF = 100000000;
    int vol[3], vis[maxn][maxn][maxn], mintimes;//vol容量
    struct state{
        int cup[3], times;
        state(){}
        state(int a, int b, int c, int t){
            cup[0] = a;
            cup[1] = b;
            cup[2] = c;
            times = t;
        }
    };
    queue<state> Q;
    void daoshui(state u){
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)//从i杯往j杯倒水,共3*3种方案
                if(i != j){//排除自己给自己倒
                    if(u.cup[i] == 0 || u.cup[j] == vol[j])//i满或者j空 跳过
                        continue;
                    int amount = min(vol[j], u.cup[i]+u.cup[j]) - u.cup[j];//amount是转移的水量 1.i杯可以将j杯装满并且还有剩余 2.i杯全部倒入j杯,j杯仍没满
                    state u2(u);
                    u2.cup[i] -= amount;
                    u2.cup[j] += amount;
                    u2.times++;//u2是转移后的新状态
                    if(!vis[u2.cup[0]][u2.cup[1]][u2.cup[2]]){//尝试入队
                        vis[u2.cup[0]][u2.cup[1]][u2.cup[2]] = 1;
                        Q.push(u2);
                    }
                }
    }
    
    void bfs(int k){
        state st(0, 0, 0, 0);//反正可以不计次数地倒满清空
        vis[0][0][0] = 1;//不是无脑插入,每次取出时检查是否重复,那样入队出队太多了;而是在插入的地方检查重复
        Q.push(st);
        while(!Q.empty()){
            state u = Q.front();
            Q.pop();
            for(int i = 0; i < 3; i++)
            if(u.cup[i] == k){
                if(u.times < mintimes)
                    mintimes = u.times;
                return;
            }//终止条件写在最前面嗯很奇妙
           int arr[3];
           for(int l = 0; l < 3; l++)//1杯
           {
               if(l == 0)
                    arr[0] = 0;//
               else if (l == 1)
                    arr[0] = vol[0];//
               else
                    arr[0] = u.cup[0];//不变
               for(int i = 0; i < 3; i++){//2杯
                    if(i == 0)
                        arr[1] = 0;
                    else if(i == 1)
                        arr[1] = vol[1];
                    else
                        arr[1] = u.cup[1];
    
                    for(int j = 0; j < 3; j++){//3杯
                        if(j == 0){
                            arr[2] = 0;
                        }
                        else if(j == 1){
                            arr[2] = vol[2];
                        }
                        else
                            arr[2] = u.cup[2];
                        daoshui(state(arr[0], arr[1], arr[2], u.times));
                    }
               }
           }
        }
    }
    int main(){
        //freopen("in.txt", "r", stdin);
        int t;
        scanf("%d", &t);
        while(t--){
            while(!Q.empty())
                Q.pop();
            int k;
            scanf("%d%d%d%d", &vol[0], &vol[1], &vol[2], &k);
            mintimes = INF;
            memset(vis, 0, sizeof(vis));
            bfs(k);
            if(mintimes < INF)
                printf("%d
    ", mintimes);
            else
                printf("-1
    ");
        }
        return 0;
    }

    以后忘了就来看

     
    搞图论是没有用的,转行做数学题了hh
  • 相关阅读:
    Emoji表情编解码库XXL-EMOJI
    代码生成平台Xxl-Code-Generator
    分布式单点登录框架XXL-SSO
    分布式爬虫框架XXL-CRAWLER
    Java对象和Excel转换工具XXL-EXCEL
    API管理平台XXL-API
    分布式缓存管理平台XXL-CACHE
    不知不觉已经写了多年代码,贴一下12年写的代码,表喷哈
    memcached安装、使用
    MySQL和Redis数据一致性问题
  • 原文地址:https://www.cnblogs.com/DearDongchen/p/7203542.html
Copyright © 2020-2023  润新知