熄灯问题 && 飞行员兄弟 && 翻棋子

简介: 熄灯问题 && 飞行员兄弟 && 翻棋子

poj 1222 熄灯问题

51.png

52.png

53.png54.png

–第二次按下同一个按钮时,将抵消第一次按下所产生的效果。

–每个按钮最多只需按一次。

–每个按钮按下的顺序对最后的结果没有影响。

–对第一行每个点亮的灯,只需按下第二行相应的灯,就可以熄

灭第一行所有的灯,那么如此重复下去,第1,2,3,4行的灯都可以熄灭。

位运算解法

//熄灯问题
#include <iostream>
#include <cstring>
using namespace std;
char old[10], lights[10], result[10];  //原数组,灯数组,结果数组
void SetBit(char &c, int i, int v)  //c代表第i行的字符,把第i行的第j位设置成v
{
    if(v) {
        c = c | (1 << i);
    }
    else 
        c = c & ~(1 << i);
}
//v = 1
//如果把第3位上的设置为1
//0010 0101 
//0010 0101 | 0000 1000 = 0010 1101   按位或运算
//v = 0
//如果把第2位上的位设置为0
//0010 0101
//~(1  << 2)= ~(0000 0100) = (1111 1011)
//0010 0101 & 1111 1011 = 0010 0001
int GetBit(char c, int i)  //取出c的第i位上的数字
{
    return (c >> i) & 1;
}
//0010   0001  右移3位   0000   0100 & 0000  0001 = 0
void FilpBit(char &c, int i)   //翻转c的第i位
{
    c = c ^ (1 << i);
}
//0010 0101
//翻转第3位上的数字
//0010 0101 ^ 0000 1000 = 0010 1101
void OutPutResult()
{
    for(int i = 0; i < 5; ++i)
        for(int j = 0; j < 6; ++j) {
            cout << GetBit(result[i], j);
            if(j < 5) cout << " ";
            else cout << endl;
        }
}
int main()
{
  int kase;
  cin>>kase;
  for(int i = 1;i <= kase ;i++)
  {
      int v, switchs;
      for(int i = 0; i < 5; ++i)
          for(int j = 0; j < 6; ++j) {
              cin >> v;
              SetBit(old[i], j, v);
          }
      for(int n = 0; n < 1 << 6; ++n) {  //6个开关,2的6次方种情况,  (1 << 6 == 2^6)
          memcpy(lights, old, sizeof(old));  //还原lights数组
          switchs = n;
          for(int i = 0; i < 5; ++i) {
              result[i] = switchs;  //  0 0 1 0 1 0
              for(int j = 0; j < 6; ++j) {
                  if(GetBit(switchs, j)) {
                      if(j > 0) FilpBit(lights[i], j - 1);  //翻转左边
                      FilpBit(lights[i], j); //翻转本身
                      if(j < 5) FilpBit(lights[i], j + 1); //翻转右边
                  }
              }
              if(i < 4) lights[i + 1] ^= switchs;
              switchs = lights[i];
          }
          if(lights[4] == 0) {
            printf("PUZZLE #%d\n",i);
              OutPutResult();
              break;
          }
      }
  }
    return 0;
}

局部替代整体

借鉴某位大佬的 博客

#include<stdio.h>
int puzzle[6][8],press[6][8];
bool guess(){
  int c,r;
  for(r=1;r<5;++r){
    for(c=1;c<7;++c){
      press[r+1][c]=(puzzle[r][c]+press[r][c-1]+press[r][c]+press[r][c+1]+press[r-1][c])%2;
    }//根据press第一行和puzzle数组计算press的其他值
  }
    for(c=1;c<7;++c){
      if((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2!=puzzle[5][c])
      return false;
    }// 
    return true;
}
void zhenghe(){//将数据进行整合
  int c;
  bool success;
  for(c=1;c<7;c++){
    press[1][c]=0;
  }
  while(guess()==false){//当没有正确答案时,继续下去。找到正确的答案为止
    press[1][1]++;
    c=1;
    while(press[1][c]>1){
      press[1][c]=0;
      c++;
      press[1][c]++;//模拟二进制,六位二进制
    }
  }
  return;
}
int main(){
  int n,i,r,c,a=1;
  scanf("%d",&n);
  for(r=0;r<6;++r){
    press[r][0]=0;
    press[r][7]=0;
  }
  for(c=1;c<7;++c){
    press[0][c]=0;
  }
  for(i=0;i<n;++i){
    for(r=1;r<6;++r){
      for(c=1;c<7;++c){
        scanf("%d",&puzzle[r][c]);//输入
      }
    }
  zhenghe();
  printf("PUZZLE #%d\n",a);a++;
  for(r=1;r<6;++r){
      for(c=1;c<7;++c){
        printf("%d ",press[r][c]);//输出
      }
      printf("\n");
    }
  }
  return 0; 
}

飞行员兄弟 4*4

55.png

56.png

#include <cstdio>
using namespace std;
char s[4];
int mp[4][4];
int main()
{
    int arr=0;
    for(int i=0;i<4; i++)
    {
        scanf("%s",s);
        for(int j=0; j<4; j++)
        {
            if(s[j] == '+')
            {
                for(int k=0; k<4; k++)
                {
                    mp[i][k] ++;
                    mp[k][j] ++;
                }
            mp[i][j] --;
          }
        }
    }
    for(int i=0; i<4; i++)
    {
        for(int j=0; j<4; j++)
        {
            if(mp[i][j] % 2 == 1)
                arr ++;
        }
    }
    printf("%d\n",arr);
    for(int i=0; i<4; i++)
    {
        for(int j=0; j<4; j++)
        {
            if(mp[i][j] % 2 == 1)
                printf("%d %d\n",i + 1, j + 1);
        }
    }
    return 0;
}

翻棋子游戏 poj 1753

57.png58.png


#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
struct node
{
    int x;         //用十进制的整数的后16位表示该节点的状态
    int steps;     //记录到达该节点的步数
    int i;         //是翻动哪个棋子到达当前的状态,避免返回以前的状态
};
bool vis[100000]={false};
char str[10];
node queue[100000];
void flip(int i,node a,node &b)    //i=当前要翻动的棋子编号(0-15),a为queue[p]的形参,b为queue[q]的引用
{
    int r=i/4,c=i%4;       //r、c为当前的要翻动的第i个棋子的行和列坐标
    b.x=a.x;               //为了不改变前一次记录的状态,先拷贝给b。再来翻棋子,记录新状态。
    b.x=b.x^(0x1<<i);         //用^0x1取反(0x1表示16进制的1)
    if(r>0)
        b.x=b.x^(0x1<<(i-4));     //翻i对应位置上面的棋子
    if(r<3)
        b.x=b.x^(0x1<<(i+4));     //翻i对应位置下面的棋子
    if(c>0)
        b.x=b.x^(0x1<<(i-1));     //翻i对应位置左边的棋子
    if(c<3)
        b.x=b.x^(0x1<<(i+1));     //翻i对应位置右边的棋子
    b.i=i;
    b.steps=a.steps+1;
}
void init()
{
    queue[0].x=0;             //初始化为16进制的0 (10进制和16进制的0是一样的)
    queue[0].steps=0;
    queue[0].i=-1;
    for(int i=0;i<4;i++)
    {
        scanf("%s",str);
        for(int j=0;j<4;j++)
        {
            if(str[j]=='b')         //黑棋对应的位置置1 (用|0x1置1)
                queue[0].x=(queue[0].x|(0x1<<i*4+j));
        }
    }
}
void bfs()
{
    int p=0,q=0;
    while(!(queue[q].x==0||queue[q].x==0xffff))     //如果不满足全0或者全1的状态
    {
        for(int i=0;i<16;i++)
        {
            if(queue[p].i==i)        
                continue;
            q++;                             //尾指针后移,为新状态开辟新的记录空间
            flip(i,queue[p],queue[q]);
            if(vis[queue[q].x])
                q--;
            vis[queue[q].x]=true;
            if(queue[q].x==0||queue[q].x==0xffff)
                break;
        }
        if(p==q)
        {
            printf("Impossible\n");
            break;
        }
        p++;                //头指针后移1位,将当前状态作为搜索的初始状态
    }
    if(queue[q].x==0||queue[q].x==0xffff)
        printf("%d",queue[q].steps);
}
int main()
{
    init();
    bfs();
    return 0;
}
相关文章
|
3天前
每日一题——圆圈中最后剩下的数字(约瑟夫环问题)
每日一题——圆圈中最后剩下的数字(约瑟夫环问题)
LeetCode-1145 二叉树着色游戏
LeetCode-1145 二叉树着色游戏
|
3天前
|
存储 XML JavaScript
圣诞节到了,用代码给对象写一颗圣诞树吧
JS是JavaScript的缩写,它是一种广泛使用的编程语言。JavaScript通常用于在web页面中添加动态内容、交互式特效和用户体验增强等功能。它是一种脚本语言,可以在浏览器中直接运行,也可以与服务器端进行交互。JavaScript可以用于创建复杂的应用程序,包括网页、手机应用、桌面应用以及游戏等。它具有广泛的应用领域,并且拥有大量的开发资源和社区支持。
69 3
|
11月前
Leecode 面试题62. 圆圈中最后剩下的数字
Leecode 面试题62. 圆圈中最后剩下的数字
46 0
|
11月前
剑指offer 70. 圆圈中最后剩下的数字
剑指offer 70. 圆圈中最后剩下的数字
36 0
|
12月前
|
算法 开发工具 索引
宝石方块游戏中三消查找算法的原理和实现
嗨!大家好,我是小蚂蚁。 今天这篇文章分享一下三消查找算法的原理和实现,其实三消的机制最早源于《宝石方块》这款经典游戏,如今三消已经属于一个游戏品类了。 最近刚好正在制作一款宝石方块游戏,顺便讲一下其中的三消查找算法。一直以为之前写过了,找了一圈发现并没有,今天就在这里补上。
285 0
|
12月前
|
小程序
做个经典宝石方块游戏
在做了一个月的进阶课程之后,终于又可以回来做游戏了。不得不说,对于我来讲做课程要比做游戏的难的多。做出来是一回事儿,讲出来又是另一回事儿了。尤其是还希望能讲的明白,讲的浅显易懂,感觉还是很难的。不过还好,做课程这件事情也是可以练习的,比如说我现在面对镜头讲一个东西的时候,就比一年前要好很多了。
105 0
|
存储 算法 索引
LeetCode:6390. 滑动子数组的美丽值
题目描述:给你一个长度为 n 的整数数组 nums ,请你求出每个长度为 k 的子数组的 美丽值 。 一个子数组的 美丽值 定义为:如果子数组中第 x 小整数 是 负数 ,那么美丽值为第 x 小的数,否则美丽值为 0 。 请你返回一个包含 n - k + 1 个整数的数组,依次 表示数组中从第一个下标开始,每个长度为 k 的子数组的 美丽值 。 子数组指的是数组中一段连续 非空 的元素序列。
|
数据安全/隐私保护
【广度优先搜索】N叉树的层序遍历 | 腐烂的橘子 | 单词接龙 | 最小基因变化 | 打开转盘锁
【广度优先搜索】N叉树的层序遍历 | 腐烂的橘子 | 单词接龙 | 最小基因变化 | 打开转盘锁
【广度优先搜索】N叉树的层序遍历 | 腐烂的橘子 | 单词接龙 | 最小基因变化 | 打开转盘锁
|
存储
【CCCC】L2-030 冰岛人 (25分) 模拟题,二叉树链式存储,从底部向上
【CCCC】L2-030 冰岛人 (25分) 模拟题,二叉树链式存储,从底部向上
163 0