• 剑指offer【面试题10 :矩形覆盖】


    题目:

    我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。
    请问用n个2 * 1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

    思路1:假设某方案中用了a个横着的小矩形、b个竖着的小矩形

    那么,n = 2*a + 1*b;可以编程求出所有的a与b;例如:n = 4的时候;解为:

    a = 0, b = 4; 

    a = 1, b = 2;

    a = 2, b = 0;

    有三组解,剩下的问题,正对一个解,都是一个排列组合问题,暂时没搞懂;

    思路2:

    如图:你知道当我们遍历一个长度为n(宽度当然是2啦)的矩形的时候;要么竖着放一个,要么横着放,只要横着放,那么下面一定也只能横着放一块 (如图横着放的红色下面一定只能再横着放一块,如图黄色块)。

    所以,当我们执行循环的时候(设每一种当前矩形的列的累加值为m,保存在vector<int>sums中),每次都有m  “+1”  和m “+2” 两种可能;我们每一个循环统计出 m = number的个数;直到 sums中的每一个m都大于 number;

      1 //我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。
      2 //请问用n个2 * 1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
      3 // 思路: 
      4 // n = 1*a + 2*b
      5 // 我们求解出来a、b,然后在求特定的排列组合
      6 #include<iostream>
      7 #include<list>
      8 #include<algorithm>
      9 #include<list>
     10 #include<vector>
     11 #include<boost/timer.hpp>
     12 using namespace std;
     13 
     14 void PrintVector(const list<int>& vec_)
     15 {
     16     for (auto& element_:vec_)
     17     {
     18         cout.width(3);
     19         cout << element_ << " ";
     20     }
     21     cout << endl;
     22 }
     23 
     24 //容器每个元素都 大于 number
     25 bool IsBigger( const list<int>& vec, int number)
     26 {
     27     for (auto& element_:vec)
     28     {
     29         if (element_ > number)
     30             continue;
     31         else
     32             return false;
     33     }
     34     return true;
     35 }
     36 
     37 int rectCover(int number) // 9
     38 {
     39     if ((number == 1) || (number == 2))
     40     {
     41         return number;
     42     }
     43     else // number >= 3
     44     {
     45         bool isbigger = false;
     46         list<int> sums;
     47         int count = 0;
     48         sums.push_back(1);
     49         sums.push_back(2);
     50         int i, j;
     51         for (int i = 1;; i++)
     52         {
     53             int sizeofsums = 2*sums.size(); // 2 4 8 16 32指数增长
     54             vector<int> temp;
     55             list<int>::iterator itr = sums.begin();
     56             //将当前sums中所有元素+1;并且将sums的size扩大一倍
     57             // 例如:sizeofsums = 8时
     58             for ( int n = 0; n <sizeofsums; n++)
     59             {
     60                 // 
     61                 if (n < (sizeofsums / 2))
     62                 {
     63                     (*itr) += 1;// sums[0]、sums[1] 、sums[2] 、sums[3]自增1 
     64                     temp.push_back(*itr);
     65                     itr++;//只能在这里
     66                 }
     67                 else
     68                 {
     69                     //sums[4]、sums[5] 、sums[6] 、sums[7]自增1(实际是+2)
     70                     sums.push_back(temp[n - (sizeofsums / 2)] + 1);// push_back让容器自动扩容;
     71                 }
     72                 
     73             }
     74             //PrintVector(sums);
     75             // 计算当前符合条件的方案数量
     76             for (auto& ele_ : sums)
     77             {
     78                 if (ele_ == number)
     79                 {
     80                     count++;
     81                 }
     82             }
     83             // 删除溢出的方案
     84             for (list<int>::iterator itr = sums.begin(); itr != sums.end();)
     85             {
     86                 if (*itr >= number)
     87                 {
     88                     itr = sums.erase(itr);
     89                 }
     90                 else
     91                 {
     92                     itr++;
     93                 }
     94             }
     95             //cout << "删除后" << endl;
     96             //PrintVector(sums);
     97             if (IsBigger(sums, number)) //如果每一个元素都大于 number;那么list<int> sums的解就被收集干净了
     98                 break;
     99         }
    100         return count;
    101     }
    102 }
    103 int main()
    104 {
    105     boost::timer timer1;
    106     cout << "ways = " << rectCover(29) << endl;//5
    107     cout << "cost of  time is :" << timer1.elapsed() << endl;
    108     cout << "ways = " << rectCover(5) << endl;//5
    109     cout << "ways = " << rectCover(4) << endl;//5
    110     cout << "ways = " << rectCover(3) << endl;//5
    111     cout << "ways = " << rectCover(2) << endl;//5
    112     cout << "ways = " << rectCover(1) << endl;//5
    113     return 1;
    114 }

  • 相关阅读:
    杂记5
    杂记4
    杂记3
    杂记2
    杂记1
    也来个网页版本的五子棋
    验证码识别
    npm publish命令
    window nginx php ci框架环境搭建
    也来个网页版本的五子棋
  • 原文地址:https://www.cnblogs.com/winslam/p/9466720.html
Copyright © 2020-2023  润新知