北大1166题

 题目连接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1166

 

1,用两个bit存储每个表的状态,涉及到位操作

2,将指定位置1,用或操作,A*B(*代表0或者1,A为前缀,B为后缀),将*置1要用C1D(C和D是全0段,两者的长度与A和B对应相等),只要将A*B与C1D相或即可得到A1B

3,将指定位置0,用与操作,A*B,将*置0要用C0D(C和D是全1段,两者的长度与A和B对应相等),只要将A*B与C0D相与即可得到A0B

4,为了方便实现2和3描述的操作用了两个辅助数组set和reset,两者可以通过基本的位运算符求取

5,还有一个比较重要的是位运算符的优先级很低的,要用括号调整

6,一直错,还是广搜代码没有写对,应该入队就设标志位,不能推迟到出队才设置!

#include <iostream>
using namespace std;

#define MAX 2000000

int set[32];
int reset[32];

void Init()
{
 int i,tmp;
 tmp = 1;
 for(i = 0;i < 32;++i)
 {
  set[i] = tmp;
  reset[i] = ~tmp;

  tmp <<= 1;
 }
}

struct Clock
{
 int time;
 int pre;
 int step;

 void Reset(int i)
 {
  time &= reset[i];
 }

 void Set(int i)
 {
  time |= set[i];
 }

 void Rotate(int i)
 {
  int b = i*2;
  if((set[b] & time) != 0)
   Reset(b);
  else if(((set[b] & time) == 0) && ((set[b+1] & time) == 0))
  {
   Set(b);
   Set(b+1);
  }
  else
  {
   Set(b);
   Reset(b+1);
  }
 }
};


Clock q[MAX];
int hd,tl;
bool visit[MAX],first;

void Print(int i)
{
 if(q[i].pre != -1)
 {
  Print(q[i].pre);
  if(first)
  {
   cout << q[i].step;
   first = false;
  }
  else
   cout << ' ' << q[i].step;
 }
}

void BFS(Clock& tar)
{
 memset(visit,0,sizeof(visit));

 Clock cur,next;
 cur.time = 0;
 cur.pre = -1;

 hd = tl = 0;
 q[tl++] = cur;
 visit[cur.time] = true;

 int i;
 while(hd != tl)
 {
  cur = q[hd++];

  for(i = 1;i <= 9;++i)
  {
   next = cur;
   switch(i)
   {
   case 1:
    next.Rotate(0);
    next.Rotate(1);
    next.Rotate(3);
    next.Rotate(4);
    next.step = 1;
    break;
   case 2:
    next.Rotate(0);
    next.Rotate(1);
    next.Rotate(2);
    next.step = 2;
    break;
   case 3:
    next.Rotate(1);
    next.Rotate(2);
    next.Rotate(4);
    next.Rotate(5);
    next.step = 3;
    break;
   case 4:
    next.Rotate(0);
    next.Rotate(3);
    next.Rotate(6);
    next.step = 4;
    break;
   case 5:
    next.Rotate(1);
    next.Rotate(3);
    next.Rotate(4);
    next.Rotate(5);
    next.Rotate(7);
    next.step = 5;
    break;
   case 6:
    next.Rotate(2);
    next.Rotate(5);
    next.Rotate(8);
    next.step = 6;
    break;
   case 7:
    next.Rotate(3);
    next.Rotate(4);
    next.Rotate(6);
    next.Rotate(7);
    next.step = 7;
    break;
   case 8:
    next.Rotate(6);
    next.Rotate(7);
    next.Rotate(8);
    next.step = 8;
    break;
   case 9:
    next.Rotate(4);
    next.Rotate(5);
    next.Rotate(7);
    next.Rotate(8);
    next.step = 9;
    break;
   }

   if(!visit[next.time])
   {
    next.pre = hd-1;
    q[tl++] = next;
    visit[next.time] = true;
    if(next.time == tar.time)
     break;
   }
  }

  if(q[tl-1].time == tar.time)
   break;
 }

 first = true;
 Print(tl-1);
}

int main()
{
 freopen("in.txt","r",stdin);

 Init();
 Clock c;
 int i,b,time[9];
 while(true)
 {
  for(i = 0;i < 9;++i)
   cin >> time[i];

  if(!cin.good())
   break;
  
  c.time = 0;
  for(i = 0;i < 9;++i)
  {
   b = i*2;
   switch(time[i])
   {
   case 0:
    c.Reset(b);
    c.Reset(b+1);
    break;
   case 1:
    c.Set(b);
    c.Reset(b+1);
    break;
   case 2:
    c.Reset(b);
    c.Set(b+1);
    break;
   case 3:
    c.Set(b);
    c.Set(b+1);
    break;
   }
  }
  BFS(c);
  cout << endl;
 }
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值