usaco Mother's Milk individual report

此题的特点在于它的解是一个向六个方向扩展的解答树,我们可以用dfs来做搜索,由于该解答树的扩展是无限的。必须做好回溯的判断标准。

对于如何写dfs的问题,我的看法是,找准某个节点的对应信息量,换句话讲,某个状态,三个瓶子里的牛奶量是进行下一次深入的参数。

所以dfs函数中要包含三个参数,进行六次递归。

在时间问题上,dfs往往比较耗时,可行的提速方法是利用队列或栈的高速缓存,或者是避免状态重复的动态规划。

dfs在写的时候尽量把操作写成函数,避免递归带来的空间爆炸。

标程dfs:

 
typedef struct State	State;
struct State {
    int a[3];
};
State//操作函数独立编写
pour(State s, int from, int to)
{
    int amt;

    amt = s.a[from];
    if(s.a[to]+amt > cap[to])
	amt = cap[to] - s.a[to];

    s.a[from] -= amt;
    s.a[to] += amt;
    return s;
}
void
search(State s)
{
    int i, j;

    if(seen[s.a[0]][s.a[1]][s.a[2]])//回溯判定
	return;

    seen[s.a[0]][s.a[1]][s.a[2]] = 1;

    if(s.a[0] == 0)	//解答的回溯判定
	canget[s.a[2]] = 1;

    for(i=0; i<3; i++)
    for(j=0; j<3; j++)
	search(pour(s, i, j));	//6次递归
}

 
dp的代码
dp的实现得益于状态的存在本身就是解答,没有相互影响得问题。(部分标程如下)
 
for(flag=1;flag;)
 {
        flag=0;//是否遍历了所有的状态
        for(i=0;i<=A;i++)
            for(j=0;j<=B;j++)
                for(k=0;k<=C;k++) {
                    if(m[i][j][k]) {
                	if(i==0) poss[k]=1;
		        if(i) {//以下的3个分支就是模拟倒牛奶的操作,有重复状态flag不会置1
	                    if(j<B) {
                                if(B-j>=i) {
                            	    if( m[0][j+i][k]==0) {
                                        m[0][j+i][k]=1;
                                	flag=1;
                            	    }
                                } else {
                            	    if( m[i-(B-j)][B][k] == 0) {
                                        m[i-(B-j)][B][k] =1;
                                        flag=1;
                                    }
                                }
                            }
                            if(k<C) {
                                if(C-k>=i) {
                                    if( m[0][j][k+i]==0) {
                                        m[0][j][k+i]=1;
                                        flag=1;
                                    }
                                }
                                else {
                                    if( m[i-(C-k)][j][C] == 0) {
                                        m[i-(C-k)][j][C] =1;
                                        flag=1;
                                    }
                                }
                            }
                        }
                        if(j) {
                            if(i<A) {
                                if(A-i>=j) {
                                    if( m[i+j][0][k]==0) {
                                        m[i+j][0][k]=1;
                                        flag=1;
                                    }
                                } else {
                                    if( m[A][j-(A-i)][k] == 0) {
                                        m[A][j-(A-i)][k] =1;
                                        flag=1;
                                    }
                                }
                            }
                            if(k<C) {
                                if(C-k>=j) {
                                    if( m[i][0][k+j]==0) {
                                        m[i][0][k+j]=1;
                                        flag=1;
                                    }
                                } else {
                                    if( m[i][j-(C-k)][C] == 0) {
                                        m[i][j-(C-k)][C] =1;
                                        flag=1;
                                    }
                                }
                            }
                        }
                        if(k) {
                            if(i<A) {
                                if(A-i>=k) {
                                    if( m[i+k][j][0]==0) {
                                        m[i+k][j][0]=1;
                                        flag=1;
                                    }
                                } else {
                                    if( m[A][j][k-(A-i)] == 0) {
                                        m[A][j][k-(A-i)] =1;
                                        flag=1;
                                    }
                                }
                            }
                            if(j<B) {
                                if(B-j>=k) {
                                    if( m[i][j+k][0]==0) {
                                        m[i][j+k][0]=1;
                                        flag=1;
                                    }
                                } else {
                                    if( m[i][B][k-(B-j)] == 0) {
                                        m[i][B][k-(B-j)] =1;
                                        flag=1;
                                    }
                                }
                            }
                        }
            }                   
        }
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值