题目地址 : http://ace.delos.com/usacoprob2?S=milk3&a=noSD7NtGmGx

这道题目,其实很简单,但是一开始并没有找到解题思路,因为“误入歧途”。总是试图去用纯数学的方法去解决,换句话说就是去试图找出该问题的规律。但这道题目是被放在USACO简单搜索那一章的,后来无奈用搜索的思路想了一下,茅塞顿开。

像这种最单纯的搜索题目,关键问题是,设计搜索过程中的状态表示,然后建立状态跳转的递归关系,最后再分析递归终止条件。

比如该题目,由于三个桶的总量是不变的,所以(a,b)表示一个中间状态,表示当前第一个桶和第二个桶的牛奶量,那么 c = mc - a - b;(ma,mb,mc 分别表示三个桶的容量)。然后可以分析出,初始状态是(0,0),接受状态为(0,x).

状态跳转也很直观,针对每一次“当前状态”有六种选择,A往B中倾倒,A往C中倾倒,B往A中倾倒,B往C中倾倒,C往A中倾倒,C往B中倾倒。

所以可以通过这道题目可以看到计算机 解决深搜题目的特点,无非就是我们人为地为计算机设置了一套“递归规则”,什么时候开始,如何状态跳转,如何判定结束。然后让计算机做“步步深入”的工作,这个工作我们不如计算机,我们如果“干想”,走不了几步,就会乱套。因为我们的大脑不象计算机,有“栈”机制,可以保存之前的状态。我们大脑厉害的地方是设定规则,计算机的强项是“存储记忆”和“遍历速度”。

/*
ID:liuweiv2
PROG:milk3
LANG:C++
*/

#include<iostream>
#include<fstream>
using namespace std;

const int W = 21;
int ma,mb,mc;
bool isOk[W];
bool vis[W][W];


void dfs(int a,int b){
    if(vis[a][b])
        return;

    vis[a][b] = true;//该状态的搜索情况做上标记,以防止重复递归。

    int c = mc - a - b;//当前状态下的a,b,c

    if(a == 0)
        isOk[c] = true;

    //a->b
    if(a+b<=mb)
        dfs(0,a+b);
    else
        dfs(a-mb+b,mb);

    //a->c
    if(a+c<=mc)
        dfs(0,b);
    else
        dfs(a-mc+c,b);

    //b->a
    if(b+a<=ma)
        dfs(b+a,0);
    else
        dfs(ma,b-ma+a);

    //b->c
    if(b+c<=mc)
        dfs(a,0);
    else
        dfs(a,b-mc+c);

    //c->a
    if(c+a<=ma)
        dfs(c+a,b);
    else
        dfs(ma,b);

    //c->b
    if(c+b<=mb)
        dfs(a,c+b);
    else
        dfs(a,mb);

}


int main(){
    ifstream infile;
    ofstream outfile;
    infile.open("milk3.in");
    outfile.open("milk3.out");

    infile>>ma>>mb>>mc;

    //memset(isOk,0,sizeof(isOk));
    //memset(vis,0,sizeof(vis));
    for(int i=0;i<W;i++)
    {
        isOk[i] = false;
        for(int j=0;j<W;j++)
            vis[i][j] = false;
    }


    dfs(0,0);


    bool first = true;
    for(int i=0;i<=mc;i++)
        if(isOk[i]){
            if(first){
                outfile<<i;
                first = false;
            }
            else
                outfile<<" "<<i;
        }
    outfile<<endl;

    return 0;
}
posted on 2012-06-04 14:53  geeker  阅读(236)  评论(1编辑  收藏  举报