微软过桥问题的C++实现

来源:互联网 发布:xt800是什么软件 编辑:程序博客网 时间:2024/04/19 14:38
#include <vector>
#include <iostream>
#include <queue>
#include <stack>
using namespace std
;

class Bridge_Crossing
{
public:
  Bridge_Crossing(vector<int> &c)
;
  void generate_solution();
private:
  class Node
;
  vector<Node>states; //一个状态向量。每一个状态保存一项,共2^(n+1)项
  vector<int>costs;//每个人过河所需要的时间。
  int person_num;
  void output();

struct State
{
  int state
;//状态值。如全在左岸则为0000(binary),过河后该位置1
  int direction;//方向,若在左岸为0,右岸为1

  State()
  {
    state
=direction=0;
  }
  

  State &operator
= (const State &s)
  {
    state
=s.state;
    direction=s.direction;
  }
  
  int hashcode()//计算hash值,即在states向量中的index
  {
    return state*
2+direction;
  }
}
;

struct Node
{
  int value
;//到该状态所需时间
  int previous;//前一状态的index
  Node()
  {
    value
=previous=0;
  }
}
;

}
;


Bridge_Crossing:: Bridge_Crossing(vector<int>&c)
{
  costs
=c;
  person_num = costs.size();
  states=vector<Node>((1<<(person_num+1)));
}

void Bridge_Crossing::generate_solution()
{
  queue<State>q
;
  q.push(State());//初始压栈(0000 0)
  
  while(!q.empty())
    {
      State s 
= q.front();
      q.pop();
      
      if(s.direction
==0) // 过河去,送两人
    {
      for(int i
=0;i<person_num-1;++i)
        {
          int flag 
= 1<<i;
          
          if((s.state&flag)
==0) //第i个人仍在左岸
        {
          for(int j
=i+1;j<person_num;++j)
            {
              
              int f2 
= 1<<j;
              if((s.state&f2)==0)//第j个人仍在左岸
            {
              State t
;
              t.state = s.state|flag|f2;//i,j两人过河。
              t.direction=1;
              int index = t.hashcode();
              Node n;
              n.previous = s.hashcode();
              n.value = states[n.previous].value+max(costs[i],costs[j]);
              if(states[index].value==0||n.value<states[index].value)
                //若以前未到此结点,或这次的值比原来的值更优
                {
                  states
[index]=n;
                }
              
              
              if(index!
=states.size()-1)
                //全部到达则无需再入队列
                q.push(t)
;
            }
            }
        }
        }
    }
      else
    {

      for(int i
=0;i<person_num;++i)
        {
          int flag 
= 1<<i;
          if((s.state&flag)!=0)
        {
          State t
;
          t.state = s.state&(~flag);
          t.direction=0;
          int index = t.hashcode();
          Node n;
          n.previous = s.hashcode();
          n.value = states[n.previous].value+costs[i];
          
          if(states
[index].value==0||n.value<states[index].value)
            {
              states
[index]=n;
            }
          if(index!
=states.size()-1)
              q.push(t)
;
        }
          
        }
    }
    }
  
  output()
;
}

void Bridge_Crossing::output()
{
  int p 
= states.size()-1;
  
  stack<int>s
;
  while(p!=0)
    {
      s.push(p)
;
      p=states[p].previous;
    }
  
  int state 
= 0;
  int direction = 0;
  
  while(!s.empty())
    {
      int t 
= s.top();
      s.pop();
      int difference= state^t;
      difference>>=1;// 删除最右边一个表示方面的位
      
      int flag
=1;

      for(int i
=0;i<person_num;++i)
    {
      
      if((difference&flag)!
=0)
        cout<<i+
1<<"号 ";
      flag<<=1;
    }
      
      cout<<(direction
==0?"过河":"返回")<<" 共"<<states[t].value<<""<<endl;
      direction^=1;
      state=t;
      
      
    }
  
}


int main()
{

  vector<int> v(
4;
  v[0]=1;
  v[1]=2;
  v[2]=5;
  v[3]=10;

  Bridge_Crossing b(v)
;
  
  b.generate_solution()
;
  
}

 
 
原创粉丝点击