Dynamic Programming based solution || Recursion + Memoization || C++  Code
\nclass Solution {\npublic:\n    int dp[1002][1002];\n    int min(int a, int b)\n    {\n        if(a<b) return a;\n        return b;\n    }\n    \n    int func(
```\nclass Solution {\npublic:\n    int dp[1002][1002];\n    int min(int a, int b)\n    {\n        if(a<b) return a;\n        return b;\n    }\n    \n    int func(string &floor, int numCarpets, int &carpetLen, int i, vector<int> &prefix)\n    {\n        //Base Cases\n        if(i>=floor.size())\n            return 0;\n        if(numCarpets==0)\n            return 0;\n        \n        //Memoization\n        if(dp[i][numCarpets]!=-1)\n            return dp[i][numCarpets];\n        \n        //Check if current tile is black, if it is then skip it\n        if(floor[i]==\'0\')\n            return dp[i][numCarpets]=func(floor, numCarpets, carpetLen, i+1, prefix);\n        \n        //temp stores the value of index where pointer i should point after the carpet covers white tiles \n        //sometimes i+len can place you out of scope of prefix array that\'s why floor.size() is also considered\n        int temp=min(i+carpetLen, floor.size())-1;\n        int white=prefix[temp];\n        if(i!=0) // i==0 is not fit for this condition(no elements before index 0)\n            white-=prefix[i-1]; // this line gives exact number of white tiles in between(covered by carpet)\n        /*Suppose 1 0 1 1 0 1 0 1 is the input floor array and carpetLen =2. Prefix array would be 1 1 2 3 3 4 4 5.\n        Let us suppose  i=2 then \n        temp=i+carpetLen-1 temp=2+2-1 temp=4-1 temp=3  \n        white=prefix[temp] white=prefix[3] white=3 \n        white=white-prefix[i-1]= white=3-prefix[2-1]= white=3-prefix[1] white=3-1 white=2*/\n        \n        \n        int pick=white+func(floor,numCarpets-1,carpetLen, i+carpetLen, prefix); //when you use a new carpet from the current index\n        int notpick=func(floor,numCarpets,carpetLen, i+1, prefix); //when you dont use a new carpet from the current index\n        \n        return dp[i][numCarpets]=max(pick, notpick); //maximum number of white tiles that can be covered by the carpet\n    }\n    \n    int minimumWhiteTiles(string floor, int numCarpets, int carpetLen) {\n        //for faster i/p o/p\n        ios_base::sync_with_stdio(false);\n        cin.tie(NULL);\n        \n        memset(dp,-1,sizeof dp);\n        \n        //prefix array is used to store total number of white tiles till current index\n        vector<int>prefix(floor.size()); \n        if(floor[0]==\'1\')\n            prefix[0]=1;\n        else\n            prefix[0]=0;\n        \n        for(int i=1; i<floor.size(); i++)\n        {\n            prefix[i]=prefix[i-1]+(floor[i]==\'1\');\n        }\n        \n        if(prefix[floor.size()-1]==0)\n            return 0;\n        \n        // minimum number of white tiles still visible = total number of white tiles - maximum number of white tiles that can be covered by the carpet\n        return prefix[floor.size()-1]-func(floor, numCarpets, carpetLen, 0, prefix); \n    }\n};\n```
['Dynamic Programming', 'Memoization', 'C']