zoukankan      html  css  js  c++  java
  • 水题(原 USACO Mother's Milk)

    【题目描述】

           可达鸭自从小霞旅行回来后一直没有什么事做(准确来说旅行的时候也是),所以它开始思考一些令人头疼的问题,以使自己能在道馆战中,展现自己真正的实力。今天它面对这样一个问题:面前有三个水杯,容量分别分别为a,b,c(下文用容量代指杯子),一开始c中装满了水,可以将杯子1里的水灌入杯子2灌注的过程中,如果杯子1的水量大于杯子2的剩余容量,那么只会将杯子2灌满,杯子1中任然会有剩余的水;如果小于则杯子1中的水全部灌入杯子2,可达鸭思考着当杯子a空着时,达到杯子c每种可能的水量最少需要几次操作,但是它在这一点上并不需要你帮忙,只是它比较懒,不愿意思考那些不可能的情况,所以它需要你告诉它当杯子a空着时杯子c中所有可能的水量。

     

     【题目输入】

       仅一行,为3个正整数a,b,c表示3个杯子的容量

    【题目输出】

       仅一行,升序输出所有可能

     

    【样例输入1】

    8 9 10

    【样例输出1】

    1 2 8 9 10

     

    【样例输入2】

    2 5 10  

    【样例输出2】

    5 6 7 8 9 10

     

    【数据范围与提示】

    a,b,c<=20

    题如其名是道水题


    学长考试第一题,我并不觉得是水题(至少我题目都没明白),还是自己功力不够,训练懈怠

     思路:

    这种倒水的搜索题还是很典型的,把初始的容量用 v[ ] 储存上,再把刚开始 st.v(0,0,c) 拉进来广搜

    广搜部分:

    • 两层循环枚举出各种倒水的情况
    • 当倒出桶为0,或倒入桶已满已经没意义,就不再考虑,continue
    • 计算出要倒的水量: int pour=min(cur.v[i]+cur.v[j],v[j])-cur.v[j];这行精炼的代码完全解释了题意,大白话来说:“能倒完倒完,倒不完倒满”。怎么做到的呢?如果“倒出桶”当前的水 加上 “倒入桶”当前的水小于“倒入桶”的限度,那就给倒完,如果超过了“倒入桶”的最大限度,那就倒入剩余容量的水,给倒满

    每有一种情况,判断是否已有,我们用一个三维的 vis[ next.v[1] ][ next.v[2] ][ next.v[3] ] 来记录,因为数据量很小,开三维毫无问题

     

    代码

    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int v[4],ans[1001],cnt;
    bool vis[21][21][21];
    
    struct node {
        int v[4],step; 
    }; 
    queue<node> q;
    
    void bfs()
    {
        node st;
        st.v[1]=0,st.v[2]=0,st.v[3]=v[3];
        q.push(st);
        while(!q.empty())
        {
            node cur=q.front();
            q.pop();
            if(cur.v[1]==0) {
                
                ans[++cnt]=cur.v[3];
            }
            
            for(int i=1;i<=3;++i) //from 
                for(int j=1;j<=3;++j) //to
                {
                    if(cur.v[i]==0 || cur.v[j]==v[j]) continue;
                    
                    node next=cur;
                    int pour=min(cur.v[i]+cur.v[j],v[j])-cur.v[j];
                    next.v[i]-=pour;
                    next.v[j]+=pour;
                    next.step=cur.step+1;
                    if(!vis[next.v[1]][next.v[2]][next.v[3]])
                    {
                        vis[next.v[1]][next.v[2]][next.v[3]]=1;
                        q.push(next);
                    }
                }    
        }
    }
    
    int main()
    {    
        for(int i=1;i<=3;++i)
        scanf("%d",&v[i]);
        vis[0][0][v[3]]=1;
        bfs();
        sort(ans+1,ans+1+cnt);
        for(int i=1;i<=cnt;++i) 
            printf("%d ",ans[i]);
        return 0;    
    }
    从0到1很难,但从1到100很容易
  • 相关阅读:
    Delphi中TFlowPanel实现滚动条效果
    Delphi组件开发-在窗体标题栏添加按钮(使用MakeObjectInstance(NewWndProc),并处理好多消息)
    减小Delphi的Exe文件大小(11种方法)
    画出太极图
    类似地图的以鼠标为中心缩放图像
    andoid x项目的优化 1
    ICON图标文件解析
    所有语言的Awesome(2)
    获取EIP(汇编语言直接给Delphi变量赋值)
    Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)
  • 原文地址:https://www.cnblogs.com/qseer/p/9494016.html
Copyright © 2011-2022 走看看