Sum of subsequences - algorithm

Consider the first integer is A, A[i] equals i-th digit of A (0-based indexing, from right to left) and the second integer is B , B[i] equals to i-th digit of B (0-based indexing, from right to left).
The lucky sum of A and B is equal to C, C[i] = max(A[i], B[i]). If i is greater than or equal to size of integer, the i-th digit is equal to 0.
For example,
the lucky sum of 47 and 729 is
max(7,9)=9
max(4,2)=4
max(0,7)=7
answer = 749
Similarly, the lucky sum of W = (74, 92, 477)
max(4,2) = 4
max(7,9) = 9
Lucky sum of 74,92 = 94
Lucky sum of W=(Lucky sum of (94,477))
which is
max(4,7)=7
max(9,7)=9
max(0,4)=4
So the lucky sum of w is=497.
The task: we are given an array W, containing n (1<=n<=50) integers.
We have to find a number of non-empty subsequences of W such that the lucky sum of integers in that subsequences is a lucky number (lucky numbers are positive integers whose decimal representation contains only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.).
Constraint: 0 < W[i] < 1e9
Examples:
W = {4,7}: answer = 3
W = {43, 87 ,44}: answer = 2
Can this problem be solved by dynamic programming?
How this problem can be solved efficiently in C++ ?

Here's what i can think of(unfinished yet):
Uses DP with bit mask. we now represent a number in the following way: every bit is categorized into five kinds:
(0) -> 0
(1,2,3) -> 1
(4) -> 2
(5,6) -> 3
(7) -> 4
(8,9) -> -1
As we can easily see, whenever a bit is 8 or 9, it can never be added into a valid solution. now we represent the number with bit-mask, which takes 5^8.
So we let f[i][s] denotes the total ways we can choose the subset from the first i numbers to make out the number whose bit-mask is s.
Here is the code i just wrote again.....
Three things remains:
use __int64 or long long instead of int for f[][].
use queue to accelerate enumeration for there are a lot of impossible status(i.e. f[][s]==0) if we enumerate with for (i = 0;i < MAXS;i++).
use f[0..1][MAXS] to reduce memory cost.
The sample code:
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 51
#define MAXS 390625 //5^8
using namespace std;
const int exp[] = {1, 5, 25, 125, 625, 3125, 15625, 78125, 390625};
int n;
int w[MAXN];
struct node{
int i;
int stat;
node(int x, int y):i(x),stat(y){}
};
queue<node> q;
__int64 f[MAXN][MAXS];
bool inq[MAXN][MAXS];
int main(){
//freopen("test.txt","r",stdin);
memset(f,0,sizeof(f));
memset(inq,0,sizeof(inq));
scanf("%d",&n);
for (int i = 0;i < n;i++) scanf("%d",&w[i]);
while (!q.empty()) q.pop();
f[0][0] = 1;
for (int i = 0;i < n;i++)
for (int j = 0;j < MAXS;j++)
if (f[i][j] > 0){
f[i + 1][j] += f[i][j];
int stat = j;
int loc = 0;
int k = 0;
for (int p = w[i];p > 0;p /= 10){
k = p % 10;
if (k <= 0) k = 0;
else if (k <= 3) k = 1;
else if (k <= 4) k = 2;
else if (k <= 6) k = 3;
else if (k <= 7) k = 4;
else k = -1;
if (k < 0) break;
int bit = stat % exp[loc + 1] / exp[loc];
if (k < bit) k = bit;
stat = stat - (bit - k) * exp[loc];
loc++;
}
if (k < 0) continue;
f[i + 1][stat] += f[i][j];
}
int ans = 0;
for (int i = 0;i < MAXS;i++){
bool flag = false;
for (int loc = 7;loc >= 0;loc--){
int bit = i % exp[loc + 1] / exp[loc];
if (bit > 0) flag = true;
if (flag == true && (bit != 2 && bit != 4)){
flag = false;
break;
}
}
if (flag == true) ans += f[n][i];
}
printf("%d\n",ans);
return 0;
}

Since every bit of the answer is independent. So update them separately and the whole algorithm takes O(n*log10(w))
Here's the code i just wrote:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXL 15
using namespace std;
int n;
int ans[MAXL];
int main(){
int i,j,w;
scanf("%d",&n);
memset(ans,0,sizeof(ans));
while (n--){
scanf("%d",&w);
i = 0;
while (w>0){
j = w % 10;
ans[i] = max(ans[i], j);
i++;
w /= 10;
}
}
bool flag = false;
for (i=MAXL-1;i>=0;i--){
if (ans[i] > 0) flag = true;
if (flag) printf("%d",ans[i]);
}
printf("\n");
return 0;
}

Related

Longest Increasing Subarray after add or subtract some element an amount less than K

Given an array and we can add or subtract some element an amount less than K to make the longest increasing subarray
Example: An array a=[6,4,3,2] and K=1; we can subtract 1 from a[2]; add 1 to a[4] so the array will be a=[6,3,3,3] and the LIS is [3,3,3]
An algorithm of complexity O(n) is possible, by considering a "state" approach.
For each index i, the state corresponds to the three values that we can get: A[i]-K, A[i], A[i]+K.
Then, for a given index, for each state s = 0, 1, 2, we can calculate the maximum increasing sequence length terminating at this state.
length[i+1][s] = 1 + max (length[i][s'], if val[i][s'] <= val[i+1][s], for s' = 0, 1, 2)
We can use the fact that length[i][s] is increasing with s.
In practice, if we are only interesting to know the final maximum length, we don't need to memorize all the length values.
Here is a simple C++ implementation, to illustrate this algorithm. It only provides the maximum length.
#include <iostream>
#include <vector>
#include <array>
#include <string>
struct Status {
std::array<int, 3> val;
std::array<int, 3> l_seq; // length sequences
};
int longuest_ascending_seq (const std::vector<int>& A, int K) {
int max_length = 0;
int n = A.size();
if (n == 0) return 0;
Status previous, current;
previous = {{A[0]-K, A[0]-K, A[0]-K}, {0, 0, 0}};
for (int i = 0; i < n; ++i) {
current.val = {A[i]-K, A[i], A[i] + K};
for (int j = 0; j < 3; ++j) {
int x = current.val[j];
if (x >= previous.val[2]) {
current.l_seq[j] = previous.l_seq[2] + 1;
} else if (x >= previous.val[1]) {
current.l_seq[j] = previous.l_seq[1] + 1;
} else if (x >= previous.val[0]) {
current.l_seq[j] = previous.l_seq[0] + 1;
} else {
current.l_seq[j] = 1;
}
}
if (current.l_seq[2] > max_length) max_length = current.l_seq[2];
std::swap (previous, current);
}
return max_length;
}
int main() {
std::vector<int> A = {6, 4, 3, 2, 0};
int K = 1;
auto ans = longuest_ascending_seq (A, K);
std::cout << ans << std::endl;
return 0;
}

How to find Kth smallest number in an array which formed by product of each element of 3 array A,B,C? (Time limit :2s)

The length of each array A,B and C <= 1000 and K <= min(10^6, na * nb * nc) (na,nb,nc is the length of each array A,B and C)
I have thought that we can run through array A and B to find all the products of A and B in O(n^2) and generate Kth number by multiply that products with element in array C. But I don't know how to exactly generate Kth number in step 2th.
In this problem, the number can be NEGATIVE
Does anyone help me about this or give me your idea how to solve this problem? Thank you!
Compute MUL = A[I] * B[J], for every 0 <= I < nA, and 0 <= J < nB
Sort MUL and the array C.
Your full expanded array is then composed of the concatenation of (nA * nB) mini-arrays where the ith mini-array is generated by multiplying MUL[i] with every element of C.
For each element in MUL, the lowest number in these mini-arrays will be MUL * C[0].
Multiply each element of MUL by C[0], and put it in a priority queue.
Pop K times from this list. Each time you pop a number, insert the number you popped multiplied by the next number in C (recall that we initially put MUL * C[0] into the priority queue), to get the next smallest number in the mini-array generated by this element of MUL.
<!-- language: cpp -->
#include <iostream>
#include <queue>
#include <algorithm>
int main() {
int na, nb, nc, K;
std::cin >> na >> nb >> nc >> K;
int a[na], b[nb], c[nc];
for (int i = 0; i < na; i++)
std::cin >> a[i];
for (int i = 0; i < nb; i++) {
std::cin >> b[i];
}
for (int i = 0; i < nc; i++) {
std::cin >> c[i];
}
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int> >, std::greater<std::pair<int, int> > > amulb;
std::sort(c, c + nc);
for (int i = 0; i < na; i++) {
for (int j = 0; j < nb; j++) {
amulb.push(std::make_pair(a[i] * b[j] * c[0], 0));
}
}
for (int i = 0; i < K; i++) {
std::pair<int, int> t = amulb.top();
if (i == K - 1) std::cout << t.first << "\n";
amulb.pop();
if (t.second != (nc - 1))
amulb.push(std::make_pair(t.first * c[t.second + 1] / c[t.second], t.second + 1));
}
return 0;
}

Dynamic Programming Coin Change Limited Coins

Dynamic Programming Change Problem (Limited Coins).
I'm trying to create a program that takes as INPUT:
int coinValues[]; //e.g [coin1,coin2,coin3]
int coinLimit[]; //e.g [2 coin1 available,1 coin2 available,...]
int amount; //the amount we want change for.
OUTPUT:
int DynProg[]; //of size amount+1.
And output should be an Array of size amount+1 of which each cell represents the optimal number of coins we need to give change for the amount of the cell's index.
EXAMPLE: Let's say that we have the cell of Array at index: 5 with a content of 2.
This means that in order to give change for the amount of 5(INDEX), you need 2(cell's content) coins (Optimal Solution).
Basically I need exactly the output of the first array of this video(C[p])
. It's exactly the same problem with the big DIFFERENCE of LIMITED COINS.
Link to Video.
Note: See the video to understand, ignore the 2nd array of the video, and have in mind that I don't need the combinations, but the DP array, so then I can find which coins to give as change.
Thank you.
Consider the next pseudocode:
for every coin nominal v = coinValues[i]:
loop coinLimit[i] times:
starting with k=0 entry, check for non-zero C[k]:
if C[k]+1 < C[k+v] then
replace C[k+v] with C[k]+1 and set S[k+v]=v
Is it clear?
O(nk) solution from an editorial I wrote a while ago:
We start with the basic DP solution that runs in O(k*sum(c)). We have our dp array, where dp[i][j] stores the least possible number of coins from the first i denominations that sum to j. We have the following transition: dp[i][j] = min(dp[i - 1][j - cnt * value[i]] + cnt) for cnt from 0 to j / value[i].
To optimize this to an O(nk) solution, we can use a deque to memorize the minimum values from the previous iteration and make the transitions O(1). The basic idea is that if we want to find the minimum of the last m values in some array, we can maintain an increasing deque that stores possible candidates for the minimum. At each step, we pop off values at the end of the deque greater than the current value before pushing the current value into the back deque. Since the current value is both further to the right and less than the values we popped off, we can be sure they will never be the minimum. Then, we pop off the first element in the deque if it is more than m elements away. The minimum value at each step is now simply the first element in the deque.
We can apply a similar optimization trick to this problem. For each coin type i, we compute the elements of the dp array in this order: For each possible value of j % value[i] in increasing order, we process the values of j which when divided by value[i] produces that remainder in increasing order. Now we can apply the deque optimization trick to find min(dp[i - 1][j - cnt * value[i]] + cnt) for cnt from 0 to j / value[i] in constant time.
Pseudocode:
let n = number of coin denominations
let k = amount of change needed
let v[i] = value of the ith denomination, 1 indexed
let c[i] = maximum number of coins of the ith denomination, 1 indexed
let dp[i][j] = the fewest number of coins needed to sum to j using the first i coin denominations
for i from 1 to k:
dp[0][i] = INF
for i from 1 to n:
for rem from 0 to v[i] - 1:
let d = empty double-ended-queue
for j from 0 to (k - rem) / v[i]:
let currval = rem + v[i] * j
if dp[i - 1][currval] is not INF:
while d is not empty and dp[i - 1][d.back() * v[i] + rem] + j - d.back() >= dp[i - 1][currval]:
d.pop_back()
d.push_back(j)
if d is not empty and j - d.front() > c[i]:
d.pop_front()
if d is empty:
dp[i][currval] = INF
else:
dp[i][currval] = dp[i - 1][d.front() * v[i] + rem] + j - d.front()
This is what you are looking for.
Assumptions made : Coin Values are in descending order
public class CoinChangeLimitedCoins {
public static void main(String[] args) {
int[] coins = { 5, 3, 2, 1 };
int[] counts = { 2, 1, 2, 1 };
int target = 9;
int[] nums = combine(coins, counts);
System.out.println(minCount(nums, target, 0, 0, 0));
}
private static int minCount(int[] nums, int target, int sum, int current, int count){
if(current > nums.length) return -1;
if(sum == target) return count;
if(sum + nums[current] <= target){
return minCount(nums, target, sum+nums[current], current+1, count+1);
} else {
return minCount(nums, target, sum, current+1, count);
}
}
private static int[] combine(int[] coins, int[] counts) {
int sum = 0;
for (int count : counts) {
sum += count;
}
int[] returnArray = new int[sum];
int returnArrayIndex = 0;
for (int i = 0; i < coins.length; i++) {
int count = counts[i];
while (count != 0) {
returnArray[returnArrayIndex] = coins[i];
returnArrayIndex++;
count--;
}
}
return returnArray;
}
}
You can check this question: Minimum coin change problem with limited amount of coins.
BTW, I created c++ program based above link's algorithm:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <limits>
using namespace std;
void copyVec(vector<int> from, vector<int> &to){
for(vector<int>::size_type i = 0; i < from.size(); i++)
to[i] = from[i];
}
vector<int> makeChangeWithLimited(int amount, vector<int> coins, vector<int> limits)
{
vector<int> change;
vector<vector<int>> coinsUsed( amount + 1 , vector<int>(coins.size()));
vector<int> minCoins(amount+1,numeric_limits<int>::max() - 1);
minCoins[0] = 0;
vector<int> limitsCopy(limits.size());
copy(limits.begin(), limits.end(), limitsCopy.begin());
for (vector<int>::size_type i = 0; i < coins.size(); ++i)
{
while (limitsCopy[i] > 0)
{
for (int j = amount; j >= 0; --j)
{
int currAmount = j + coins[i];
if (currAmount <= amount)
{
if (minCoins[currAmount] > minCoins[j] + 1)
{
minCoins[currAmount] = minCoins[j] + 1;
copyVec(coinsUsed[j], coinsUsed[currAmount]);
coinsUsed[currAmount][i] += 1;
}
}
}
limitsCopy[i] -= 1;
}
}
if (minCoins[amount] == numeric_limits<int>::max() - 1)
{
return change;
}
copy(coinsUsed[amount].begin(),coinsUsed[amount].end(), back_inserter(change) );
return change;
}
int main()
{
vector<int> coins;
coins.push_back(20);
coins.push_back(50);
coins.push_back(100);
coins.push_back(200);
vector<int> limits;
limits.push_back(100);
limits.push_back(100);
limits.push_back(50);
limits.push_back(20);
int amount = 0;
cin >> amount;
while(amount){
vector<int> change = makeChangeWithLimited(amount,coins,limits);
for(vector<int>::size_type i = 0; i < change.size(); i++){
cout << change[i] << "x" << coins[i] << endl;
}
if(change.empty()){
cout << "IMPOSSIBE\n";
}
cin >> amount;
}
system("pause");
return 0;
}
Code in c#
private static int MinCoinsChangeWithLimitedCoins(int[] coins, int[] counts, int sum)
{
var dp = new int[sum + 1];
Array.Fill(dp, int.MaxValue);
dp[0] = 0;
for (int i = 0; i < coins.Length; i++) // n
{
int coin = coins[i];
for (int j = 0; j < counts[i]; j++) //
{
for (int s = sum; s >= coin ; s--) // sum
{
int remainder = s - coin;
if (remainder >= 0 && dp[remainder] != int.MaxValue)
{
dp[s] = Math.Min(1 + dp[remainder], dp[s]);
}
}
}
}
return dp[sum] == int.MaxValue ? -1 : dp[sum];
}

How can I maximise the number of ribbon piece for a ribbon of given length n?

I have a ribbon, its length is n. I want to cut the ribbon in a way that fulfils the following two conditions:
1. After the cutting each ribbon piece should have length a, b or c.
2. After the cutting the number of ribbon pieces should be maximum.
Find the number of maximum pieces after required cutting.
Input is of the form n,a,b,c where n is the original length of ribbon, and a,b,c are the required lengths of the ribbon.
For eg: I/P = 5 5 3 2
O/P = 2
Now, I am able to realize that this should follow a DP solution. A one dimensional DP where dp[n] represents the maximum number of ways for ribbon of length n.
Now, I am not sure if the recurrence relations will be of the form,
dp[n] = dp[n-a] + a;
dp[n] = dp[n-b] + b;
dp[n] = dp[n-c] + c;
Is this correct or there is some other way?
Edit: Implementation according to the first post:
#include <iostream>
#include <cmath>
using namespace std;
int dp[100000];
int maxi (int a,int b,int c);
int main (void)
{
int n,a,b,c;
cin>>n>>a>>b>>c;
for (int i = 0; i <= n; i++)
{
if ( i == 0 )
dp[i] = 0;
else
dp[i] = maxi(dp[i-a],dp[i-b],dp[i-c])+1;
}
cout<<dp[n]<<"\n";
return 0;
}
int maxi (int a,int b,int c)
{
int ret;
if ( a > b )
ret = a;
else
ret = b;
if ( ret < c )
ret = c;
return ret;
}
if n < 0:
dp[n] = -infinity
if n == 0:
dp[n] = 0
if n > 0:
dp[n] = 1 + max(dp[n-a], dp[n-b], dp[n-c])
for (int i = 0; i <= n; i++)
{
if (i == 0)
dp[i] = 0;
else {
int A = (i-a>=0) ? dp[i-a] : -n-1;
int B = (i-b>=0) ? dp[i-b] : -n-1;
int C = (i-c>=0) ? dp[i-c] : -n-1;
dp[i] = maxi(A,B,C)+1;
}
}

Counting tilings of a rectangle

I am trying to solve this problem but I can't find a solution:
A board consisting of squares arranged into N rows and M columns is given. A tiling of this board is a pattern of tiles that covers it. A tiling is interesting if:
only tiles of size 1x1 and/or 2x2 are used;
each tile of size 1x1 covers exactly one whole square;
each tile of size 2x2 covers exactly four whole squares;
each square of the board is covered by exactly one tile.
For example, the following images show a few interesting tilings of a board of size 4 rows and 3 columns:
http://dabi.altervista.org/images/task.img.4x3_tilings_example.gif
Two interesting tilings of a board are different if there exists at least one square on the board that is covered with a tile of size 1x1 in one tiling and with a tile of size 2x2 in the other. For example, all tilings shown in the images above are different.
Write a function
int count_tilings(int N, int M);
that, given two integers N and M, returns the remainder modulo 10,000,007 of the number of different interesting tilings of a board of size N rows and M columns.
Assume that:
N is an integer within the range [1..1,000,000];
M is an integer within the range [1..7].
For example, given N = 4 and M = 3, the function should return 11, because there are 11 different interesting tilings of a board of size 4 rows and 3 columns:
http://dabi.altervista.org/images/task.img.4x3_tilings_all.gif
for (4,3) the result is 11, for (6,5) the result is 1213.
I tried the following but it doesn't work:
static public int count_tilings ( int N,int M ) {
int result=1;
if ((N==1)||(M==1)) return 1;
result=result+(N-1)*(M-1);
int max_tiling= (int) ((int)(Math.ceil(N/2))*(Math.ceil(M/2)));
System.out.println(max_tiling);
for (int i=2; i<=(max_tiling);i++){
if (N>=2*i){
int n=i+(N-i);
int k=i;
//System.out.println("M-1->"+(M-1) +"i->"+i);
System.out.println("(M-1)^i)->"+(Math.pow((M-1),i)));
System.out.println( "n="+n+ " k="+k);
System.out.println(combinations(n, k));
if (N-i*2>0){
result+= Math.pow((M-1),i)*combinations(n, k);
}else{
result+= Math.pow((M-1),i);
}
}
if (M>=2*i){
int n=i+(M-i);
int k=i;
System.out.println("(N-1)^i)->"+(Math.pow((N-1),i)));
System.out.println( "n="+n+ " k="+k);
System.out.println(combinations(n, k));
if (M-i*2>0){
result+= Math.pow((N-1),i)*combinations(n, k);
}else{
result+= Math.pow((N-1),i);
}
}
}
return result;
}
static long combinations(int n, int k) {
/*binomial coefficient*/
long coeff = 1;
for (int i = n - k + 1; i <= n; i++) {
coeff *= i;
}
for (int i = 1; i <= k; i++) {
coeff /= i;
}
return coeff;
}
Since this is homework I won't give a full solution, but I'll give you some hints.
First here's a recursive solution:
class Program
{
// Important note:
// The value of masks given here is hard-coded for m == 5.
// In a complete solution, you need to calculate the masks for the
// actual value of m given. See explanation in answer for more details.
int[] masks = { 0, 3, 6, 12, 15, 24, 27, 30 };
int CountTilings(int n, int m, int s = 0)
{
if (n == 1) { return 1; }
int result = 0;
foreach (int mask in masks)
{
if ((mask & s) == 0)
{
result += CountTilings(n - 1, m, mask);
}
}
return result;
}
public static void Main()
{
Program p = new Program();
int result = p.CountTilings(6, 5);
Console.WriteLine(result);
}
}
See it working online: ideone
Note that I've added an extra parameter s. This stores the contents of the first column. If the first column is empty, s = 0. If the first column contains some filled squares the corresponding bits in s are set. Initially s = 0, but when a 2 x 2 tile is placed, this fills up some squares in the next column, and that will mean that s will be non-zero in the recursive call.
The masks variable is hard-coded but in a complete solution it needs to be calculated based on the actual value of m. The values stored in masks make more sense if you look at their binary representations:
00000
00011
00110
01100
01111
11000
11011
11110
In other words, it's all the ways of setting pairs of bits in a binary number with m bits. You can write some code to generate all these possiblities. Or since there are only 7 possible values of m, you could also just hard-code all seven possibilities for masks.
There are however two serious problems with the recursive solution.
It will overflow the stack for large values of N.
It requires exponential time to calculate. It is incredibly slow even for small values of N
Both these problems can be solved by rewriting the algorithm to be iterative. Keep m constant and initalize the result for n = 1 for all possible values of s to be 1. This is because if you only have one column you must use only 1x1 tiles, and there is only one way to do this.
Now you can calculate n = 2 for all possible values of s by using the results from n = 1. This can be repeated until you reach n = N. This algorithm completes in linear time with respect to N, and requires constant space.
Here is a recursive solution:
// time used : 27 min
#include <set>
#include <vector>
#include <iostream>
using namespace std;
void placement(int n, set< vector <int> > & p){
for (int i = 0; i < n -1 ; i ++){
for (set<vector<int> > :: iterator j = p.begin(); j != p.end(); j ++){
vector <int> temp = *j;
if (temp[i] == 1 || temp[i+1] == 1) continue;
temp[i] = 1; temp[i+1] = 1;
p.insert(temp);
}
}
}
vector<vector<int> > placement( int n){
if (n > 7) throw "error";
set <vector <int> > p;
vector <int> temp (n,0);
p.insert (temp);
for (int i = 0; i < 3; i ++) placement(n, p);
vector <vector <int> > s;
s.assign (p.begin(), p.end());
return s;
}
bool tryput(vector <vector <int> > &board, int current, vector<int> & comb){
for (int i = 0; i < comb.size(); i ++){
if ((board[current][i] == 1 || board[current+1][i]) && comb[i] == 1) return false;
}
return true;
}
void put(vector <vector <int> > &board, int current, vector<int> & comb){
for (int i = 0; i < comb.size(); i ++){
if (comb[i] == 1){
board[current][i] = 1;
board[current+1][i] = 1;
}
}
return;
}
void undo(vector <vector <int> > &board, int current, vector<int> & comb){
for (int i = 0; i < comb.size(); i ++){
if (comb[i] == 1){
board[current][i] = 0;
board[current+1][i] = 0;
}
}
return;
}
int place (vector <vector <int> > &board, int current, vector < vector <int> > & all_comb){
int m = board.size();
if (current >= m) throw "error";
if (current == m - 1) return 1;
int count = 0;
for (int i = 0; i < all_comb.size(); i ++){
if (tryput(board, current, all_comb[i])){
put(board, current, all_comb[i]);
count += place(board, current+1, all_comb) % 10000007;
undo(board, current, all_comb[i]);
}
}
return count;
}
int place (int m, int n){
if (m == 0) return 0;
if (m == 1) return 1;
vector < vector <int> > all_comb = placement(n);
vector <vector <int> > board(m, vector<int>(n, 0));
return place (board, 0, all_comb);
}
int main(){
cout << place(3, 4) << endl;
return 0;
}
time complexity O(n^3 * exp(m))
to reduce the space usage try bit vector.
to reduce the time complexity to O(m*(n^3)), try dynamic programming.
to reduce the time complexity to O(log(m) * n^3) try divide and conquer + dynamic programming.
good luck

Resources