您的位置:首页 > 移动开发 > IOS开发

[USACO] 从Mother’s Milk看搜索

2012-06-06 01:33 204 查看
源地址:http://www.cnblogs.com/HappyAngel/archive/2011/06/12/2079131.html

最近由于想锻炼小型程序编写能力,所以打算做完USACO,当然这个是比较水的题目,但对于业余ACM爱好

者的我来说还是有一定难度的,拿来练手和学习还是很不错的。

  Mother’s Milk是一个搜索的题目,总的来说难度不大,但是我在一开始的时候并没有那么轻易的看出状

态的转移方式,在状态转移那里卡了很久,一直在想怎么模拟这个倒水的过程?其实我是陷入题目的误

区,明知道是到搜索题目,就应该以搜索的方式来思考,那么怎么思考搜索题目的解法呢?

  首先,搜索的题目最重要的就是找到状态,就是怎么样一个东西算作此题的状态,亦即解空间的一个节

点,这是首要任务,如果连状态都没定义好,后续的一切都是浮云。

  然后呢,就是要思考从一个状态有几种转移方式,就是从解空间的一个节点出发有条边和其他节点相连,

这样就能够大概估计到解空间的大小,以考虑是用深搜呢,还是广搜。如果空间需求不大,解可能在离根节

点较近的地方,就果断广搜,其他就深搜吧。我广搜一般是用队列,深搜是用递归实现的,这中间要考虑几点:
4000

  考虑用何种方式判重?(布尔数组?)

  考虑是否可以剪枝?(例如USACO的 The Clocks要考虑到同一种类型的旋转转3次后会回到原点,

因此果断剪掉3次以上同类型旋转)

  最后就是编码实现了,然后考虑各种优化问题,例如查找改成哈希等等。

  用这种想法思考Mother’s milk, 考虑到状态就是 (A桶中牛奶的数量,B桶中牛奶的数量),因为牛奶的

总数量是确定的,所以上述序列足可确定一个解空间的节点。然后思考可以有几种转移方式?很明显,总共

三个桶,因此就是6种:A->B A->C B->A B->C C->A C->B。以A->B来说,这样转移之后状态是什么呢?A的

牛奶数应该是max(0, a+b-B),其中a,b是A和B桶中原来牛奶的数量,A,B是A和B桶的容量。B的牛奶数是

min(a+b, B),其他的以此类推。

  估算一下解空间的大小吧,由于题目限制A,B,C的值是1-20之间,所以总共的状态,最多,也就

20*20=400,所以,用广搜就行。代码如下:

1: /*
2: ID:happyan3
3: PROG:milk3
4: LANG:C++
5: */
6:
7: #include <iostream>
8: #include <fstream>
9: #include <queue>
10: #include <vector>
11: #include <algorithm>
12: #include <cstring>
13: #include <cstdlib>
14: #include <bitset>
15:
16: using namespace std;
17:
18: struct state
19: {
20:  int a;
21:  int b;
22:  int c;
23: };
24:
25: const int num=21;
26: bool bFlag[num][num];//判重
27:
28: //广搜
29: //pre: 输入a,b,c是 桶的容量
30: //post: 输出res,是 c的可能数,未排序
31: void GetAnswer(int a, int b, int c, vector<int>& res)
32: {
33:  state init_state;
34:  init_state.a=0;
35:  init_state.b=0;
36:  init_state.c=c;
37:
38:  queue<state> q;
39:  q.push(init_state);
40:  while(!q.empty())
41:  {
42:   state s = q.front();
43:   q.pop();
44:   if(s.a>=0 && s.b>=0 && s.c>=0)
45:   {
46:    if(s.a==0)
47:    {
48:     if(res.end()==find(res.begin(),res.end(),s.c))
49:      res.push_back(s.c);
50:    }
51:    bFlag[s.a][s.b]=true;
52:    //all 6 possibilities
53:
54:    state temp = s;
55:    //1 a->b
56:    s.a = max(0,s.a+s.b-b);
57:    s.b = min(temp.a+s.b,b);
58:    if(!bFlag[s.a][s.b])
59:     q.push(s);
60:    s=temp;
61:
62:    //2 a->c
63:    s.a = max(0,s.a+s.c-c);
64:    s.c = min(temp.a+s.c,c);
65:    if(!bFlag[s.a][s.b])
66:     q.push(s);
67:    s=temp;
68:
69:    //3 b->a
70:    s.b = max(0,s.b+s.a-a);
71:    s.a = min(temp.b+s.a,a);
72:    if(!bFlag[s.a][s.b])
73:     q.push(s);
74:    s=temp;
75:
76:    //4 b->c
77:    s.b = max(0,s.b+s.c-c);
78:    s.c = min(temp.b+s.c,c);
79:    if(!bFlag[s.a][s.b])
80:     q.push(s);
81:    s=temp;
82:
83:    //5 c->b
84:    s.c = max(0,s.c+s.b-b);
85:    s.b = min(temp.c+s.b,b);
86:    if(!bFlag[s.a][s.b])
87:     q.push(s);
88:    s=temp;
89:
90:    //6 c->a
91:    s.c = max(0,s.c+s.a-a);
92:    s.a = min(temp.c+s.a,a);
93:    if(!bFlag[s.a][s.b])
94:     q.push(s);
95:    s=temp;
96:   }
97:  }
98: }
99:
100: int main(void)
101: {
102:  ifstream fin;
103:  fin.open("milk3.in");
104:  ofstream fout;
105:  fout.open("milk3.out");
106:
107:  int a=0;
108:  int b=0;
109:  int c=0;
110:  fin>>a>>b>>c;
111:
112:  for(int i=0; i < num; i++)
113:  {
114:   for(int j=0; j < num; j++)
115:    bFlag[i][j]=false;
116:  }
117:
118:  vector<int> res;
119:
120:  GetAnswer(a,b,c,res);
121:
122:  sort(res.begin(),res.end());
123:  for(vector<int>::iterator it=res.begin(); it!=res.end()-1; it++)
124:  {
125:   fout<<(*it)<<" ";
126:  }
127:
128:  fout<<res.back()<<endl;
129:
130:  fin.close();
131:  fout.close();
132:  //getchar();
133:  //getchar();
134:  //getchar();
135:  return 0;
136: }


/*
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息