USACO 1.4.4 Mother's Milk

原题链接:http://cerberus.delos.com:791/usacoprob2?a=s1DTJaMre3q&S=milk3

分析与思路:不难看出共有六种到牛奶的方式,a->b,a->c,b->a,b->c,c->a,c->b。但是每次倒完后的状态不一定一样的,不一样的状态在进行六种不同方式的倾倒,

                       又可以产生不一样的状态。这就需要来记录每个状态是否出现过,当出现过时就直接返回到函数出口,进行上一层的下一次变换,若没有出现过此状态就继

                       续进行这六种方式的变换。深度优先搜索示意图如下:

以下是代码执行流程图的一部分(以8,9,10为例进行搜索):

代码:

#include <iostream>
#include <fstream>
#include <string>
 
using namespace std;
int A,B,C;
int used[21][21][21],recorder[21];
void DFS(int a,int b,int c)
{
 if(used[a][b][c])return ;
 else used[a][b][c]=1;
  if(a==0&&!recorder[c])
    recorder[c]=1;
 //把c倒入a
 if(c>=A-a)DFS(A,b,c-A+a);
 else DFS(a+c,b,0);
 //把c倒入b
 if(c>=B-b)DFS(a,B,c-B+b);
 else DFS(a,b+c,0);
 //把b倒入a
 if(b>=A-a)DFS(A,b-A+a,c);
 else DFS(a+b,0,c);
 //把b倒入c
 if(b>=C-c)DFS(a,b-C+c,C);
 else DFS(a,0,b+c);
 //把a倒入b
 if(a>=B-b)DFS(a-B+b,B,c);
 else DFS(0,a+b,c);
 //把a倒入c
 if(a>=C-c)DFS(a-C+c,b,C);
 else DFS(0,b,a+c);
 
}
int main() {
    ofstream fout ("milk3.out");
    ifstream fin ("milk3.in");
    cin>>A>>B>>C;
    DFS(0,0,C);
    int count=0;
    for(int i=0;i<=C;i++)
    {
     if(recorder[i])
       {
         count++;
        if(count==1)
          cout<<i;
        else
          cout<<" "<<i;
       }
    }
    cout<<endl;
    return 0;
}

再来看看类似的题目:之前做的全国软件大赛的泊松分酒。

题目要求由用户输入:各个容器的容量,开始的状态,和要求的目标油量,通过计算输出实现的步骤。以上代码只要记录一下成功时的遍历路径即可

#include <iostream>
#include <fstream>
#include <string>

using namespace std;
int A,B,C;
int used[21][21][21],recorder[21];
int path[100][3];
int path_index=0;
int N,count=0;
void DFS(int a,int b,int c)
{
 path[path_index][0]=a;
 path[path_index][1]=b;
 path[path_index][2]=c;
 ++path_index;
 if(used[a][b][c])return ;
 else used[a][b][c]=1;
  if(a==N||b==N||c==N){
  count++;
    cout<<"第"<<count<<"个"<<endl;
    for(int i=0;i<path_index;i++)
     cout<<path[i][0]<<" "<<path[i][1]<<" "<<path[i][2]<<endl;
    cout<<"--------------------------------------------"<<endl;
    }
 //把c倒入a
 if(c>=A-a)DFS(A,b,c-A+a);
 else DFS(a+c,b,0);
 --path_index;
 //把c倒入b
 if(c>=B-b)DFS(a,B,c-B+b);
 else DFS(a,b+c,0);
  --path_index;
 //把b倒入a
 if(b>=A-a)DFS(A,b-A+a,c);
 else DFS(a+b,0,c);
  --path_index;
 //把b倒入c
 if(b>=C-c)DFS(a,b-C+c,C);
 else DFS(a,0,b+c);
  --path_index;
 //把a倒入b
 if(a>=B-b)DFS(a-B+b,B,c);
 else DFS(0,a+b,c);
  --path_index;
 //把a倒入c
 if(a>=C-c)DFS(a-C+c,b,C);
 else DFS(0,b,a+c);
  --path_index;
}
int main() {
    ofstream fout ("milk3.out");
    ifstream fin ("milk3.in");
    cin>>A>>B>>C;
    int a,b,c;
    cin>>a>>b>>c;
    cin>>N;
    DFS(a,b,c);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值