• [USACO] 从Mother’s Milk看搜索


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

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

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

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

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

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

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

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

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

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

    •   考虑用何种方式判重?(布尔数组?)
    •   考虑是否可以剪枝?(例如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: }
    /*
    
  • 相关阅读:
    Redis详解----- 缓存穿透、缓存击穿、缓存雪崩
    mysql存储时间
    MAT入门到精通
    meven依赖思考记录
    线程池原理
    vscode + wsl2
    java架构师学习路线-高级
    java架构师学习路线-初级
    (二)垃圾回收
    (一)内存区域
  • 原文地址:https://www.cnblogs.com/HappyAngel/p/2079131.html
Copyright © 2020-2023  润新知