您的位置:首页 > 其它

usaco Mother's Milk individual report

2015-08-14 08:26 232 查看
此题的特点在于它的解是一个向六个方向扩展的解答树,我们可以用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不会置1if(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;}}}}}}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  usaco 算法