水题(原 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;    
}

猜你喜欢

转载自www.cnblogs.com/qseer/p/9494016.html