【问题标题】:Improving time complexity of chessboard pattern提高棋盘图案的时间复杂度
【发布时间】:2019-10-30 15:08:03
【问题描述】:

我编写了一个程序来打印棋盘图案。 它是这样的: (cmets解释逻辑和变量)

#include<iostream>
#include<vector>
#include<string>
#include<fstream>
#include<cstdlib>
using namespace std;
int block_size = 8; //block_size * block_size is the size of each block on the board
int dim = 8; //8 blocks on every row or column, each block containing block_size * block_size pixels
int res = dim * block_size; //total number of pixels is res * res (resolution)

int main(){
    int size = 8;
    vector<vector<int> > vec(res);  

    for (int i = 0; i < res; i++) { 

        vec[i] = vector<int>(res); 
        for (int j = 0; j < res; j++) {
            vec[i][j] = 0; 
        }
    }//initialize all pixels to 0
    //int count=0;
    /*
    allocate black or white pixels based on odd/even status of array indices which are picked
    based on multiples of block_size
    ex. i,j = 0,4,8,16...
    pixels are allocated from the starting point of a particular coordinate like so: two for loops for i,j + d 
    where 0<=d<block_size
    */
    for (int i = 0; i < res; i=i+block_size) { 
        for (int j = 0; j < res; j=j+block_size) {
            //cout<<count<<" ";
            //count++;
            //cout<<i/block_size;
            if (int ((i/block_size)%2 == 0)){
                if(int ((j/block_size)%2 == 0)){
                    for(int k=i;k<i+block_size;k++){
                        for (int l=j;l<j+block_size;l++){
                            vec[k][l]=0;
                        }
                    }
                }
                else{
                    for(int k=i;k<i+block_size;k++){
                        for (int l=j;l<j+block_size;l++){
                            vec[k][l]=255;
                        }
                    }
                }

                }
                else{
                    if(int ((j/block_size)%2 == 0)){
                    for(int k=i;k<i+block_size;k++){
                        for (int l=j;l<j+block_size;l++){
                            vec[k][l]=255;
                        }
                    }
                }
                else{
                    for(int k=i;k<i+block_size;k++){
                        for (int l=j;l<j+block_size;l++){
                            vec[k][l]=0;
                        }
                    }
                }

                }

            }
        }

    cout<<endl;
    /*
    for (int i = 0; i < size; i++) { 
        for (int j = 0; j < vec[i].size(); j++) 
            cout << vec[i][j] << " "; 
        cout << endl; 
    }
    */
    string filename = "chessboard.pgm";
    ofstream pgmFile(filename);


    pgmFile << "P2" << endl;
    pgmFile << res << " " << res << endl;
    pgmFile << 255 << endl;


    for(int i=0;i<res;i++){
        for(int j=0;j<res;j++){
            pgmFile << vec[i][j] << " ";
        }
        pgmFile << endl;
    }

    pgmFile.close();
    return 0;
}

程序的输出被输入到一个pgm图像中,然后写入一个文件中查看,(Irfanview可以用来查看pgm图像)。
算法如下:
--根据选取的数组索引的奇/偶状态分配黑色或白色像素
基于 block_size 的倍数
前任。 i,j = 0,4,8,16...
--pixels 从特定坐标的起点分配:2 for 循环 for i,j + d 其中 d 范围从 0 到 block_size,不包括 block_size
现在,看起来复杂度是 O(n^4)。关于我可以采取哪些步骤来降低复杂性的任何想法?

【问题讨论】:

  • 欢迎来到 SO!我不太明白这是 O(n^4)。这里是什么?如果您访问每个像素一次或两次,那么我看不出您如何期望对此有任何复杂性改进。
  • 嗨,我的意思是输入的大小。是的,这是真的,每个像素只被访问一次或两次,但我想也许有一种比我使用的算法更有效的算法。
  • 不,不是 O(N^4)。由于您必须访问每个像素固定的次数,并且您已经访问了每个像素固定的次数,因此您无法提高复杂度。不过,您也许可以提高效率。效率不等于复杂性。

标签: c++ algorithm optimization time-complexity


【解决方案1】:

您的时间复杂度已经是最优的。当然,您正在对输入进行几次传递,但该常量被忽略,复杂性归结为图像中的像素数(或 O(side_length2 * block_size2 ) 或 O(res2) 或仅 O(n) 如果 n 是图像大小)。

话虽如此,有很多重复的代码,你可以完全消除向量,这使得你的空间复杂度保持不变。

这里是重写,只保留要点:

#include <cstdlib>
#include <fstream>

int main() {
    int block_size = 8;
    int dim = 8;
    int res = dim * block_size;
    std::ofstream pgm("chessboard.pgm");
    pgm << "P2\n" << res << " " << res << "\n255\n";

    for (int i = 0; i < res; i++) {
        for (int j = 0; j < res; j++) {
            pgm << ((j / block_size + i / block_size) % 2 ? 255 : 0) << " ";
        }

        pgm << "\n";
    }

    pgm.close();
    return 0;
}

最后:国际象棋的左下角通常有一个黑色方块,因此您可以考虑反转颜色。

【讨论】:

    【解决方案2】:

    棋盘有漂亮的图案。它交替排列偶数行(从黑色方块开始)和奇数行(从白色方块开始)。这表明了一个自然的程序结构:

        for (row_pair = 0; row_pair < dim / 2; row_pair++) {
            emit_row(something_even);
            emit_row(something_odd);
        }
    

    反过来,每一行由block 相同的细(一个像素高)线组成。为偶数行和奇数行做好准备;只有两个。

        line_t even_line = prepare_even_line(block_size);
        line_t odd_line = prepare_odd_line(block_size);
    

    和使用一样

        void emit_row(line_t& line) {
            for (int i = 0; i < block_size; i++) {
                emit_line(line);
            }
        }
    

    现在可以

        for (row_pair = 0; row_pair < dim / 2; row_pair++) {
            emit_row(even_line);
            emit_row(odd_line);
        }
    

    剩下的就是弄清楚line_t应该是什么,以及如何准备细线。 emit 应该是不言而喻的。

    【讨论】:

      【解决方案3】:

      你可以使用这样的东西(这是控制台中的完整代码)。

      在您的实现中每个像素都被访问一次,复杂度也是O(res^2),但看起来更简单。

      block_size-s 等于 2 的幂,rxry 可能通过按位运算计算

      int main()
      {
          int block_size = 4; //block_size * block_size is the size of each block on the board
          int dim = 4; //8 blocks on every row or column, each block containing block_size * block_size pixels
          int res = dim * block_size; //total number of pixels is res * res (resolution)
          vector<vector<int> > vec(res);
      
          for (int i = 0; i < res; i++) {
              vec[i] = vector<int>(res);
              }
      
          for (int y = 0; y < res; y++) {
              int ry = ((y % (block_size * 2)) < block_size) ? 0 : 1;
              for (int x = 0; x < res; x++) {
                  int rx = ((x % (block_size * 2)) < block_size) ? 0 : 1;
                  vec[y][x] = 255 * (ry ^ rx);
                  cout << vec[y][x] << "\t";
              }
              cout << "\n";
          }
      }
      

      Jarod42 提出的更简单的方法:

      for (int y = 0; y < res; y++) {
          for (int x = 0; x < res; x++) {
              vec[y][x] = ((y / block_size) + (x / block_size)) % 2 == 0 ? 0 : 255;
      

      4x4 的结果:

      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      0       0       0       0       255     255     255     255     0       0       0       0       255     255     255     255
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      255     255     255     255     0       0       0       0       255     255     255     255     0       0       0       0
      

      【讨论】:

      • 或类似vec[y][x] = ((y / block_size) + (x / block_size)) % 2 == 0 ? 0 : 255;block_x + block_y 的奇偶校验)。
      • @Jarod42 是的,这更简单
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-17
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      相关资源
      最近更新 更多