• [POJ] 2965.The Pilots Brothers' refrigerator


    The Pilots Brothers’ refrigerator

    Time Limit: 1000MS      Memory Limit: 65536K
    Total Submissions: 29786        Accepted: 11550     Special Judge
    

    Description

    The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to 
    open a refrigerator.
    There are 16 handles on the refrigerator door. Every handle can be in one of two states: open or 
    matrix 4х4. You can change the state of a handle in any location [i, j] (1 ≤ i, j ≤ 4). However, 
    this also changes states of all handles in row i and all handles in column j.
    The task is to determine the minimum number of handle switching necessary to open the refrigerator.
    

    Input

    The input contains four lines. Each of the four lines contains four characters describing the 
    initial state of appropriate handles. A symbol “+” means that the handle is in closed state, whereas 
    the symbol “−” means “open”. At least one of the handles is initially closed.
    

    Output

    The first line of the input contains N – the minimum number of switching. The rest N lines describe 
    switching sequence. Each of the lines contains a row number and a column number of the matrix 
    separated by one or more spaces. If there are several solutions, you may give any one of them.
    

    Sample Input

    -+--
    ----
    ----
    -+--
    

    Sample Output

    6
    1 1
    1 3
    1 4
    4 1
    4 3
    4 4
    

    题意:有4×4个把手的冰箱,规定转换把手的同时也要转换这一行和列的把手,问给定一个冰箱的把手状态,至少需要转换多少次,能使得冰箱的把手全为open(-)。
    思路:一开始想着和POJ1753差不多,遂改了改1753的代码,结果超时了。。

    #include <algorithm>
    #include <bitset>
    #include <cstdio>
    #include <cstring>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    int map = 0;
    int state[16] = {4383, 8751, 17487, 34959, 4593, 8946, 17652, 35064,
                     7953, 12066, 20292, 36744, 61713, 61986, 62532, 63624};
    int step[16] = {0};
    
    //得到state数据
    void init()
    {
      for (int i = 1; i <= 16; i++)
      {
        int v = 0, k = 1 << (i - 1);
        v |= k;
        int move = 1;
        for (int j = 4 - (i % 4); j > 0 && j != 4; j--)
        {
          v |= k << move;
          ++move;
        }
        move = 1;
        for (int j = (i % 4) ? (i % 4 - 1) : 3; j > 0; j--)
        {
          v |= k >> move;
          ++move;
        }
        move = 4;
        for (int j = (i % 4) ? (3 - i / 4) : (4 - i / 4); j > 0 && j != 4; j--)
        {
          v |= k << move;
          move += 4;
        }
        move = 4;
        for (int j = i / 4; j > 0; j--)
        {
          v |= k >> move;
          move += 4;
        }
        state[i - 1] = v;
      }
    }
    //打开第i个冰箱
    void flip(int i)
    {
      map ^= state[i];
      step[i] = !step[i];
    }
    //判断是否完成
    bool check() { return (map == 0xFFFF); }
    //寻找解 总共还要开n个门,当前开第i个门
    bool find(int n, int i)
    {
      if (n == 0)
        return check();
      for (; i < 16; i++)
      {
        flip(i);
        if (find(n - 1, i))
          return true;
        flip(i); //遍历一种后翻转回来以便下次遍历
      }
      return false;
    }
    
    int times()
    {
      int time = 0;
      for (int i = 0; i < 16; i++)
        if (step[i])
          ++time;
      return time;
    }
    int main()
    {
      // init();
    
      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 4; j++)
        {
          map <<= 1;
          if (getchar() == '-')
            map |= 1;
        }
        getchar();
      }
    
      for (int i = 0; i < 16; i++)
      {
        if (find(i, 0))
        {
          cout << times() << endl;
    
          for (int i = 3; i >= 0; i--)
            for (int j = 3; j >= 0; j--)
            {
              if (step[i * 4 + j])
                cout << 4 - i << ' ' << 4 - j << endl;
            }
          system("pause");
          return 0;
        }
      }
      system("pause");
      return 0;
    }

    于是又百度了,看到个大神的思路

    先看一个简单的问题,如何把'+'变成'-'而不改变其他位置上的状态?
    答案是将该位置(i,j)及位置所在的行(i)和列(j)上所有的handle更新一次,结果该位置被更新了7次,相应行(i)和列(j)的
    handle被更新了6次,剩下的被更新了4次.被更新偶数次的handle不会造成最终状态的改变. 
    因此得出高效解法,在每次输入碰到'+'的时候,自增该位置与相应的行和列,当输入结束后,遍历数组,所有为奇数的位置则是操作 
    的位置,而奇数位置的个数之和则是最终的操作次数.
    
    #include <algorithm>
    #include <bitset>
    #include <cstdio>
    #include <cstring>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    int a[4][4] = {0};
    int main()
    {
      char c;
      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 4; j++)
        {
          cin >> c;
          if (c == '+')
          {
            for (int k = 0; k < 4; k++)
            {
              //将同行列的都操作一次
              a[i][k] ^= 1;
              a[k][j] ^= 1;
            }
            a[i][j] ^= 1;
          }
        }
      }
    
      int sum = 0;
      for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
          if (a[i][j])
            sum++;
      printf("%d
    ", sum);
    
      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 4; j++)
        {
          if (a[i][j])
            printf("%d %d
    ", i + 1, j + 1);
        }
      }
      return 0;
    }
  • 相关阅读:
    IPv4地址被用光,IPv6将接手
    杀猪盘
    大家都应该看看这个贴子,会让你心明眼亮。 注意到这些变化了吗?中国正在发生的100个变化,越往后读越震惊!
    区块链在中国怎么练?
    区块链到底是什么样的技术呢?
    2019感恩节
    人工智能、大数据、物联网、区块链,四大新科技PK,你更看好谁?
    vue遇见的问题(2)---imported multiple times(转载)
    drf-序列化器的理解
    Django rest_framework序列化many=True参数解释
  • 原文地址:https://www.cnblogs.com/ruoh3kou/p/9893455.html
Copyright © 2020-2023  润新知