1.题意:有一组3*3的只有时针的挂钟阵列,每个时钟只有0,3,6,9三种状态;对时针阵列有9种操作,每种操作只对特点的几个时钟拨一次针,即将时针顺时针波动90度,现在试求从初试状态到阵列全部指向0的状态所需要的最小操作数的操作方案;

2.输入输出:输入给出阵列初始状态,0,1,2,3分别表示0,3,6,9;要求输出最快方案的操作序列;

3.分析:IOI 1994的考题,BFS是比较容易想到的方法之一,关键是如何简洁的表示和改变BFS过程中的阵列状态;这里使用位运算的方法;具体如下:

首先一共9个时钟,每个时钟有0,1,2,3这4种状态,所以每个时钟可以由两位二进制数表示,则整个阵列就可以用18位二进制数表示,这里表示的问题就解决了;下一步就是如何表示"转动90度了",这里分三步,1)从状态中取出要调整的那个钟,2)对取出的sub部分进行模拟转动90度的操作,3)将处理完的sub放回原状态;经过这样的三个步骤之后,对一个钟的修改就完成了,针对每种操作,对这个操作内的每个时钟进行修改,就对当前状态完成了操作;

综上所述,这样的位运算方法使得表示更加简洁,计算的更快;具体代码如下:

 # include <cstdio>
# include <iostream>
# include <queue>
# include <cstring>
# include <stack>
using namespace std;
const int MAXN=<<;
int clock[];
int vis[MAXN];
struct Node
{
int status,move,pre;
Node (){}
Node(int ss,int mm,int pp)
{
status=ss;
move=mm;
pre=pp;
}
}L[MAXN];
int M[][]=
{{,,,,-},{,,,-,-},{,,,,-},
{,,,-,-},{,,,,},{,,,-,-},
{,,,,-},{,,,-,-},{,,,,-}};
void Init()
{
for(int i=;i<;i++)
scanf("%d",&clock[i]);
memset(vis,,sizeof(vis));
}
void Solve()
{
queue<Node> Q;
int start=;
int len=;
for(int i=;i<;i++)
start|=(clock[i]<<(i<<));
Q.push(Node(start,-,-));
vis[start]=;
while(!Q.empty())
{
Node temp=Q.front();
Q.pop();
L[len++]=temp;
if(temp.status==)
break;
//printf("%d\n",temp.move);
for(int i=;i<;i++)
{
int nclock=;
int nstatus=temp.status;
for(int j=;j<;j++)
if(M[i][j]>=)
{
nstatus&= ((<<)-) ^ (<<(*(M[i][j])));
//"1111[目标位]1111",把待处理部分位的位置清零
nclock=(temp.status >> (*(M[i][j]))) & ;
//取出要处理的部分位
nstatus|=((nclock+) & ) << (*(M[i][j]));
//填入处理后的部分位
}
if(!vis[nstatus])
{
Q.push(Node(nstatus,i,len-));
vis[nstatus]=;
}
}
}
len--;
stack<int> S;
while()
{
S.push(L[len].move+);
len=L[len].pre;
if(L[len].pre<)
break;
}
printf("%d",S.top());
S.pop();
while(!S.empty())
{
int t=S.top();
S.pop();
printf(" %d",t);
}
printf("\n");
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
Init();
Solve();
return ;
}

eg.位运算举例

1.两位二进制数表示一个状态,4个一组,即8位二进制数表示一组状态

2.要实现的操作,对第i+1个状态进行加一操作

3.大体思路:1)待处理状态num做一个副本n; 2)num把要处理掉的那一位挖空 ;3)把待处理单位sub从n取出;

4)对sub操作 ;5)把sub塞回去

 void Init()
{
int num=;
for(int i=;i<;i++)
num|=(Num[i]<<(i*));
}
void Change(int i)
{
int n=num;
num&=((<<)-)^(<<(i*));
//把要处理的那一位挖空为什么是3呢,因为二进制"11"为3,正好把两个二进制位"挖空"
int sub=(n>>(i*))&;//这样除了最低的两位其他的都会与0做&运算,都扑街了
sub+=;
num|=(sub<<(*i));
}

POJ 1166 The Clocks [BFS] [位运算]的更多相关文章

  1. Poj 1166 The Clocks(bfs)

    题目链接:http://poj.org/problem?id=1166 思路分析:题目要求求出一个最短的操作序列来使所有的clock为0,所以使用bfs: <1>被搜索结点的父子关系的组织 ...

  2. POJ 1753 bfs+位运算

    T_T ++运算符和+1不一样.(i+1)%4 忘带小括号了.bfs函数是bool 型,忘记返回false时的情况了.噢....debug快哭了...... DESCRIPTION:求最少的步骤.使得 ...

  3. [poj]开关类问题 枚举 位运算

    poj 1222  EXTENDED LIGHTS OUT 开关只有两种方案 按和不按,按两次相当于关 只用枚举第一排开关的按法即可,剩下的行为使上一排的灯全部关闭,按法可以确定,并且是唯一的. 最后 ...

  4. HDU5627--Clarke and MST (bfs+位运算)

    http://www.cnblogs.com/wenruo/p/5188495.html Clarke and MST Time Limit: 2000/1000 MS (Java/Others) M ...

  5. Vijos 1206 CoVH之再破难关 [BFS] [位运算]

    1.题意:一个由01组成的4*4的矩阵,可以实现相邻元素交换位置的操作,给出初试状态和目标状态,试求最少操作数的方案: 2.输入输出:输入给出初试矩阵和目标矩阵:要求输出最小操作的次数: 3.分析:输 ...

  6. poj 2965 The Pilots Brothers' refrigerator枚举(bfs+位运算)

    //题目:http://poj.org/problem?id=2965//题意:电冰箱有16个把手,每个把手两种状态(开‘-’或关‘+’),只有在所有把手都打开时,门才开,输入数据是个4*4的矩阵,因 ...

  7. POJ 1753 Flip Game (状态压缩 bfs+位运算)

    Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 square ...

  8. [POJ] 2453 An Easy Problem [位运算]

    An Easy Problem   Description As we known, data stored in the computers is in binary form. The probl ...

  9. POJ 1166 The Clocks (暴搜)

    发现对这样的模拟题根本没啥思路了,本来准备用bfs的.可是结果超时了,这是參考别的人代码写的: #include <stdio.h> #include <iostream> # ...

随机推荐

  1. 基于MaxCompute的数仓数据质量管理

    声明 本文中介绍的非功能性规范均为建议性规范,产品功能无强制,仅供指导. 参考文献 <大数据之路——阿里巴巴大数据实践>——阿里巴巴数据技术及产品部 著. 背景及目的 数据对一个企业来说已 ...

  2. 微信小程序入门到实战(1)-基础知识

    1.微信小程序介绍 微信小程序,简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用. 1.1. 为什么是微信 ...

  3. 从零学React Native之03页面导航

    之前我们介绍了RN相关的知识: 是时候了解React Native了 从零学React Native之01创建第一个程序 从零学React Native之02状态机 本篇主要介绍页面导航 上一篇文章给 ...

  4. docker oracle install

    https://hub.docker.com/r/9fevrier/oracle-11g Informations Oracle directory : /opt/oracle Data direct ...

  5. @loj - 3022@ 「CQOI2017」老 C 的方块

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 老 C 是个程序员. 作为一个懒惰的程序员,老 C 经常在电脑上 ...

  6. 给radio添加点击事件

    1.单独给每个radio添加点击事件 <fieldset id="form-gra-time"> <legend>请选择日期粒度:</legend&g ...

  7. phpstorm鼠标显示问题

    https://segmentfault.com/q/1010000004319802 使用phpstorm,不知道碰到了什么键,鼠标变成了一个字符那么宽的灰色色块,原来是一根很细的竖线,怎么弄?没法 ...

  8. 你看Http的 三次握手

    你看Http的 三次握手 按层次分,TCP位于传输层,而且TCP协议能够确认数据是否送达到对方,所以在客户端请求资源的时候,你得让俺知道咱俩关系是不是已经确定了啊,对不.这跟谈恋爱一样一样的,得先确定 ...

  9. 利用sort对数字排序

    sort,可排序字符串,按照ASCII码排序. 但也可以穿一个比较函数,实现比较数组内容,排序数组的功能. var arr = [40, 32, 45, 89, 93, 0, 46, 74]; var ...

  10. Python--day64--内容回顾

    1,内容回顾 1.ORM外键操作 图书表和出版社表 多对一的关系 #书 class Book(models.Model): id = models.AutoField(primary_key=True ...